bash 重命名 file/add 文件名中的整数,在多个子目录中具有各种扩展名
bash rename file/add integer in filename with various extensions in multiple subdirectories
我想使用 bash 将一个整数插入到多个子目录中具有各种扩展名的文件名中。
示例:
./trial2/foo.hhh
--> ./trial2/foo1.hhh
./trial2/trial3/foo.txt
--> ./trial2/trial3/foo1.txt
我试图将文件名与扩展名分开,并在两者之间插入整数:
i=123
find . -type f -exec sh -c ' echo mv "[=12=]" "${0%.*}${i}.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo.hhh
但是变量输出${i}
没有打印出来。为什么?
如果我改为:
find . -type f -exec sh -c ' mv "[=13=]" "${0%.*}123.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo123.hhh
号码已打印。但是,我需要变量 ${i}
因为它将在包装 for 循环中定义。
编辑
你快到了;你只是打了一个引用的微妙之处。 i
在当前 shell 中声明,因此需要通过 find
以某种方式传递到 sh
运行 中。在您当前的命令中,${i}
是单引号,因此在将引用的 material 传递给 sh
.
之前,bash
不会对其进行解释
正如查尔斯·达菲所建议的那样:
find . -type f -exec sh -c ' echo mv "[=10=]" "${0%.*}.${0##*.}" ' {} "$i" \;
在 sh
命令中,[=19=]
就是 {}
,如您所知。 </code> 是 <code>sh
的第二个参数,即 "$i"
(i
扩展为单个单词)。 sh
命令不是 ${i}
,而是使用 </code> 来访问该参数(<code>i
的副本)。
原创
在这个例子中,i
被插入到当前的shell中。
Before: find . -type f -exec sh -c ' echo mv "[=11=]" "${0%.*}${i}.${0##*.}" ' {} \;
After: find . -type f -exec sh -c ' echo mv "[=11=]" "${0%.*}'"${i}"'.${0##*.}" ' {} \;
^^ ^^
'"${i}"'
将您从单引号中删除,然后扩展 i
,然后将您带回单引号中。这样,您传递给 sh
的命令包含您想要的 i
的值。
在 [=12=]
中传递 $i
,在 </code> 中传递你的文件名,然后你可以从 <code>-exec ... {} \;
更改为 -exec ... {} +
,因此仅使用一个 sh
实例可以重命名多个文件。
以下需要 bash,但生成的 mv
命令即使在存在恶意或混淆文件名(包含空格、换行符、控制字符等)的情况下也保证是正确的:
find . -type f -exec bash -c '
logcmd() { printf "%q " "$@"; printf "\n"; } # a more accurate replacement for echo
for f; do
logcmd mv "$f" "${f%.*}[=10=].${f##*.}"
done' "$i" {} +
我想使用 bash 将一个整数插入到多个子目录中具有各种扩展名的文件名中。
示例:
./trial2/foo.hhh
-->./trial2/foo1.hhh
./trial2/trial3/foo.txt
-->./trial2/trial3/foo1.txt
我试图将文件名与扩展名分开,并在两者之间插入整数:
i=123
find . -type f -exec sh -c ' echo mv "[=12=]" "${0%.*}${i}.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo.hhh
但是变量输出${i}
没有打印出来。为什么?
如果我改为:
find . -type f -exec sh -c ' mv "[=13=]" "${0%.*}123.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo123.hhh
号码已打印。但是,我需要变量 ${i}
因为它将在包装 for 循环中定义。
编辑
你快到了;你只是打了一个引用的微妙之处。 i
在当前 shell 中声明,因此需要通过 find
以某种方式传递到 sh
运行 中。在您当前的命令中,${i}
是单引号,因此在将引用的 material 传递给 sh
.
bash
不会对其进行解释
正如查尔斯·达菲所建议的那样:
find . -type f -exec sh -c ' echo mv "[=10=]" "${0%.*}.${0##*.}" ' {} "$i" \;
在 sh
命令中,[=19=]
就是 {}
,如您所知。 </code> 是 <code>sh
的第二个参数,即 "$i"
(i
扩展为单个单词)。 sh
命令不是 ${i}
,而是使用 </code> 来访问该参数(<code>i
的副本)。
原创
在这个例子中,i
被插入到当前的shell中。
Before: find . -type f -exec sh -c ' echo mv "[=11=]" "${0%.*}${i}.${0##*.}" ' {} \;
After: find . -type f -exec sh -c ' echo mv "[=11=]" "${0%.*}'"${i}"'.${0##*.}" ' {} \;
^^ ^^
'"${i}"'
将您从单引号中删除,然后扩展 i
,然后将您带回单引号中。这样,您传递给 sh
的命令包含您想要的 i
的值。
在 [=12=]
中传递 $i
,在 </code> 中传递你的文件名,然后你可以从 <code>-exec ... {} \;
更改为 -exec ... {} +
,因此仅使用一个 sh
实例可以重命名多个文件。
以下需要 bash,但生成的 mv
命令即使在存在恶意或混淆文件名(包含空格、换行符、控制字符等)的情况下也保证是正确的:
find . -type f -exec bash -c '
logcmd() { printf "%q " "$@"; printf "\n"; } # a more accurate replacement for echo
for f; do
logcmd mv "$f" "${f%.*}[=10=].${f##*.}"
done' "$i" {} +