【问题标题】:How to execute a command on multiple files with different extensions on the shell?如何在 shell 上对多个具有不同扩展名的文件执行命令?
【发布时间】:2021-08-06 21:27:49
【问题描述】:

我想在具有不同文件扩展名的目录中的所有文件上执行一个以文件名作为参数的命令。我试过这个:

for i in *.jpg *.docx *.gdi; 
 do 
  mycommand dosth -i "$i" -o "${i%.*}.myext"; 
 done 

但是,如果文件夹中不存在其中一个文件扩展名,我会收到一条错误消息,提示“找不到文件”。如何更改脚本?

【问题讨论】:

  • 你用的是什么外壳?符合 POSIX 的 shell 将不匹配的字符串视为文字字符串,而如果模式不匹配,zsh 会立即引发错误。许多 shell 可以选择忽略不匹配的模式,但这不是 POSIX 规范的一部分。
  • 我在 docker 中使用它: FROM debian:10-slim ... ENTRYPOINT for i in .jpg *.docx *.gdi;执行我的命令 dosth -i "$i" -o "${i%.}.myext";完成

标签: shell


【解决方案1】:

由于 Debian 使用dash,因此没有选项可以忽略不匹配的模式。您可以通过检查名为$i 的文件是否存在来区分匹配结果和不匹配模式。如果没有,那么它显然不是路径名扩展的结果(它只产生现有文件,除了竞争条件。)

for i in *.jpg *.docx *.gdi
do 
    [ -e "$i" ] || continue  # E.g., if $i == "*.jpg" after no JPG files were found
    mycommand dosth -i "$i" -o "${i%.*}.myext"
done 

在 Dockerfile 中,由于整个命令必须在一个逻辑行上,因此分号是必需的:

ENTRYPOINT for i in *.jpg *.docx *.gdi; do \
     [ -e "$i" ] || continue; \
     mycommand dosth -i "$i" -o "${i%.*}.myext"; \
    done

【讨论】:

  • 我认为有一个“;”继续后失踪?但它似乎有效!
  • 您只需要; 就可以将同一物理行上的命令分开。终止mycommand 行的; 是允许的,但不是必需的。
  • (虽然在 Dockerfile ENTRYPOINT 命令的上下文中,是的,你确实需要 ;。)
  • 好的,这回答了我的问题。非常感谢。作为奖励:我问如果存在“myext”文件,如何跳过它?但这确实是一个奖励。非常感谢。这将是开源 docker 容器的一部分。 =)
  • 问了一个关于“跳过现有文件”的新问题stackoverflow.com/questions/68682632/…
【解决方案2】:

我建议使用 来搜索multiple extensions,如下所示:

find . -type f \( -iname \*.jpg -o -iname \*.gdi -o -iname \*. docx \) -exec mycommand {} \;

-exec 可以根据需要使用更多参数进行更改。
How to run find -exec?


基于commends,一种生成外壳的解决方案,因此我们可以使用替换:

find . -type f \( -iname \*.jpg -o -iname \*.gdi -o -iname \*. docx \) -exec sh -c 'mycommand dosth -i "$0" -o "${0%.*}.myext"; ' {} \;

How to substitute string in {} in "find (...) -exec (...) {} \;" bash command?

【讨论】:

  • 这看起来很简单,我明白这一点。但是如何像在当前解决方案中一样使用“mycommand”中的文件名?
  • {} 是一个占位符,表示当前找到的文件,作为参数传递给mycommand
  • 我试过但在这里失败了:"${i%.*}.myext";这将是 ${{}%.*}.myext 但失败了。如何从 {} 中删除扩展程序?但是解决方案真的很好!
  • 请看我的编辑@Marc。我建议生成一个新的 shell,以便我们可以正常使用变量替换。
  • 啊,对于找到的每个带有“find”的文件,您都创建一个新的shell并使用旧命令。整洁。
猜你喜欢
  • 2016-08-10
  • 1970-01-01
  • 2014-07-01
  • 2017-04-04
  • 2012-11-13
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
相关资源
最近更新 更多