Bash, run script on every .jpg file in a directory with subdirectories

use*_*532 5 unix bash

I have some working code, it's very simple - it copies every*.jpg file, renames it into*1.jpg, no worries.

for i in *.jpg; do cp $i ${i%%.jpg}1.jpg;  done
Run Code Online (Sandbox Code Playgroud)

how can I run this, so that it works on every file in a directory, every file in the subdirectories of that directory

example directory structure:

    test/test1/test2/somefile.jpg
    test/anotherfile.jpg
    test/test1/file.jpg
etc
Run Code Online (Sandbox Code Playgroud)

Bri*_*ell 6

以递归方式对目录结构执行任何操作的命令是find:

find . -name "*.jpg" -exec bash -c 'file="{}"; cp "$file" "${file%%.jpg}1.jpg"' \;
Run Code Online (Sandbox Code Playgroud)

使用-exec而不是for i in $(find ...)将处理包含空格的文件名.当然,还有一个引用问题; 如果文件名包含a ",file="{}"则会扩展为file="name containing "quote characters"",这显然已被破坏(file将成为name containing quote并将尝试执行characters命令).

如果您有这样的文件名,或者您可以使用,则打印出用空字符分隔的每个文件名(在文件名中不允许)-print0,并使用while read -d $'\0' i循环覆盖空分隔的结果:

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

与任何像这样的复杂命令一样,最好在不执行任何操作的情况下对其进行测试,以确保在运行之前将其扩展为合理的命令.执行此操作的最佳方法是在其前面添加实际命令echo,因此您将看到它将运行的命令,而不是运行它:

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

一旦你对其进行了眼球处理并且结果看起来很好,请将其移除echo并再次运行以使其真实运行.