Bash,在子目录的目录中的每个.jpg文件上运行脚本

时间:2012-11-05 03:16:33

标签: bash unix

我有一些工作代码,它非常简单 - 它复制每个* .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 个答案:

答案 0 :(得分: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并再次运行它以使其真实运行。

答案 1 :(得分:2)

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

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

p / s:我在cp的参数周围添加引号,以防文件名中有空格或诸如此类的东西。