Mir*_*age 18 shell find rename
我有一个名为的文件夹/home/user/temps,其中包含 487 个文件夹。在每个文件夹中,我都有一个名为 thumb.png 的文件。
我想将所有名为 thumb.png 的文件复制到一个单独的文件夹中,并根据它们来自的文件夹重命名它们。
干得好:
for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;
Run Code Online (Sandbox Code Playgroud)
编辑:
顺便说一句,规范的智慧是,使用find它是一个坏主意——简单地使用外壳扩展更可靠。此外,这是假设bash,但我认为这是一个安全的假设:)
编辑2:
为清楚起见,我将其分解:
# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do
# replace 'temps' with 'new_folder' in the path
# '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
new_file=${file/temps/new_folder};
# drop '/thumb' from the path
# '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
cp "$file" "${new_file/\/thumb/}";
done;
Run Code Online (Sandbox Code Playgroud)
${var/Pattern/Replacement}可以在此处找到有关该构造的详细信息。
cp行中的引号对于处理文件名中的空格和换行符等很重要。
这适用于任意深度的子目录:
find ... | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done
Run Code Online (Sandbox Code Playgroud)
例子
$ cd /home/user
$ find temps/ -name "thumb.png" | while IFS= read -r f; do cp -v "$f" "newdir/${f//\//_}"; done
`temps/thumb.png' -> `newdir/temps_thumb.png'
`temps/dir3/thumb.png' -> `newdir/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `newdir/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `newdir/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `newdir/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `newdir/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `newdir/temps_dir2_dir21_thumb.png'
Run Code Online (Sandbox Code Playgroud)
有趣的部分是参数扩展 ${f//\//_}。它获取f(带有路径的文件名)的内容,并替换每次出现的/with _。
注意:结果取决于工作目录和查找的路径参数。我从 temps 的父目录执行了命令。前置cp有echo看到什么将被执行。
find ... | while IFS= read -r f; do echo cp -v "$f" "newdir/${f//\//_}"; done
^^^^
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
33159 次 |
| 最近记录: |