在一个带有子目录的目录中,针对每个 .jpg 文件执行脚本的 Bash 命令

5

我有一些可用的代码,非常简单 - 它会复制每个*.jpg文件,将其重命名为*1.jpg,不用担心。

for i in *.jpg; do cp $i ${i%%.jpg}1.jpg;  done

如何运行这个程序,使其在目录中的每个文件以及该目录子目录中的每个文件中都有效

示例目录结构:

    test/test1/test2/somefile.jpg
    test/anotherfile.jpg
    test/test1/file.jpg
etc

2
每个子目录中的每个文件 = 递归地 - nickhar
2个回答

6

对于目录结构递归执行任何操作的命令是find

find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' \;

使用-exec而不是for i in $(find ...)将处理包含空格的文件名。当然,仍然有一个引用陷阱;如果文件名包含",则file="{}"将扩展为file="name containing "quote characters"",这显然是错误的(file将变成name containing quote并尝试执行characters命令)。
如果您有这样的文件名,或者可能有这样的文件名,则使用-print0打印出每个文件名,并用while read -d $'\0' i循环遍历以 null 为分隔符的结果。
find . -name "*.jpg" -print0 | \
    (while read -d $'\0' i; do cp "$i" "${i%%.jpg}1.jpg";  done)

像这样的复杂命令,最好在执行之前先测试一下它是否展开成了可理解的内容。进行此操作的最佳方法是在实际命令前加上echo,这样您不会运行该命令,而是会看到其将要运行的命令:

find . -name "*.jpg" -print0 | \
    (while read -d $'\0' i; do echo cp "$i" "${i%%.jpg}1.jpg";  done)

一旦您已经检查过,并且结果看起来不错,就可以删除echo并重新运行它以实际运行。


find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' ;这是正确的脚本,非常感谢。 - user1051532

2

如果您使用的是Bash 4,您可以使用globstar来启用递归文件名扩展(即匹配子目录中的文件)

shopt -s globstar
for i in **/*.jpg; do cp "$i" "${i%%.jpg}1.jpg";  done

附注:我在cp命令的参数周围添加了引号,以防文件名中有空格或其他字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接