请注意,由于您的文件名包含空格(或者至少是有趣的),您应该"$i"
在mv
命令中使用双引号,并在echo
. 如果文件名中只有单个空格并且没有制表符或换行符,则您在回显中“摆脱它”,但是如果您不将文件名括在双引号中并且它确实包含两个相邻的空格,则会破坏文件名,或前导空格,或尾随空格,或......通常,$(...)
也使用而不是反引号。
通过提供几个(一或两个)示例输入文件名和预期的相应输出文件名,您的问题将得到改善。我们所能知道的是,当您使用空格进行拆分时(-F" "
似乎几乎没有必要),文件名至少有 5 个部分,其中只保留第一个、第三个和第五个部分。您可能在输出中生成反斜杠以保留名称中的空格,而不是因为您认为文件名中的反斜杠是个好主意。(也就是说,反斜杠不会出现在磁盘上的名称中。)
既然你有一个循环,我这样做的方式awk
是:
for file in *
do
name=$(echo "$file" | awk '{print $1 " - S0" $3 "E" $5 ".avi"}')
mv "$file" "$name"
done
这样做有充分的理由。分配保留了输出中的空格等awk
(砍掉尾随的换行符,但仅此而已)。然后mv
命令行很简单,使用双引号来防止出现问题。
试:
for file in *
do
mv "$file" $(echo "$file" | awk '{print $1 " - S0" $3 "E" $5 ".avi"}')
done
让您陷入麻烦,因为管道的输出被 shell 重新扫描并拆分,您必须防止拆分(因此原始代码中的反斜杠)并担心其他 shell 元字符(如果节目名称中有撇号怎么办? , 例如)。
但是,您可以将整个$(...)
引号括起来,然后一切正常——我本来想说“如预期的那样”,但实际上并没有如我预期的那样。但是对两者进行测试bash
并ksh
表明这有效:
for file in *
do
mv "$file" "$(echo "$file" | awk '{print $1 " - S0" $3 "E" $5 ".avi"}')"
done
外面的双引号只是简单地防止shell扩展 的输出,$(...)
使用$(...)
大大简化了生活。简单地用$(...)
反引号替换会产生各种问题;在反引号内,您必须逃避各种事情。但似乎符号$(
中的$(...)
暂停了当前的双引号字符串搜索,并开始搜索以)
对中间内容的“正常”解释的结束,这给出了所需的结果。
我认为两行(赋值加使用)更容易理解,但是这个版本在双引号内有复杂的命令替换也可以。
这是一些测试代码,假设您当前没有在当前目录中调用spaced-out
的目录(并且您在当前目录中确实具有写权限):
mkdir spaced-out
(
cd spaced-out
# Create files with spaces in the names
for file in "part1 x part2 y part3" "show1 a show2 b show3" \
" leader1 x leader2 y leader3 "
do
echo hello world > "$file"
done
ls
ls -l
# Rename the files
for file in *
do
mv "$file" "$(echo "$file" | awk '{print $1 " - S0" $3 "E" $5 ".avi"}')"
done
# Show results and clean up
ls -l
rm -f *
)
rmdir spaced-out
当作为脚本 ( bash rename.script
) 运行时,它会生成:
leader1 x leader2 y leader3 part1 x part2 y part3 show1 a show2 b show3
total 24
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 leader1 x leader2 y leader3
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 part1 x part2 y part3
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 show1 a show2 b show3
total 24
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 leader1 - S0leader2Eleader3.avi
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 part1 - S0part2Epart3.avi
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:02 show1 - S0show2Eshow3.avi
当运行 as 时bash -x rename.script
,它会生成:
+ mkdir spaced-out
+ cd spaced-out
+ for file in '"part1 x part2 y part3"' '"show1 a show2 b show3"' '" leader1 x leader2 y leader3 "'
+ echo hello world
+ for file in '"part1 x part2 y part3"' '"show1 a show2 b show3"' '" leader1 x leader2 y leader3 "'
+ echo hello world
+ for file in '"part1 x part2 y part3"' '"show1 a show2 b show3"' '" leader1 x leader2 y leader3 "'
+ echo hello world
+ ls
leader1 x leader2 y leader3 part1 x part2 y part3 show1 a show2 b show3
+ ls -l
total 24
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 leader1 x leader2 y leader3
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 part1 x part2 y part3
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 show1 a show2 b show3
+ for file in '*'
++ echo ' leader1 x leader2 y leader3 '
++ awk '{print $1 " - S0" $3 "E" $5 ".avi"}'
+ mv ' leader1 x leader2 y leader3 ' 'leader1 - S0leader2Eleader3.avi'
+ for file in '*'
++ echo 'part1 x part2 y part3'
++ awk '{print $1 " - S0" $3 "E" $5 ".avi"}'
+ mv 'part1 x part2 y part3' 'part1 - S0part2Epart3.avi'
+ for file in '*'
++ echo 'show1 a show2 b show3'
++ awk '{print $1 " - S0" $3 "E" $5 ".avi"}'
+ mv 'show1 a show2 b show3' 'show1 - S0show2Eshow3.avi'
+ ls -l
total 24
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 leader1 - S0leader2Eleader3.avi
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 part1 - S0part2Epart3.avi
-rw-r--r-- 1 jleffler eng 12 Jul 6 08:03 show1 - S0show2Eshow3.avi
+ rm -f 'leader1 - S0leader2Eleader3.avi' 'part1 - S0part2Epart3.avi' 'show1 - S0show2Eshow3.avi'
+ rmdir spaced-out
双倍行距文件名(可选地带有前导和/或尾随空格)对于声称使用包含空格的文件名的脚本通常是一个非常好的测试。此代码不管理包含换行符的文件名;该awk
脚本将一个名称视为两行输入,这不是我们想要的。可以固定;除非你需要你的脚本绝对防弹(例如,因为它是给客户的——客户做最糟糕的事情,而且文件名中带有换行符的文件名在他们的能力范围内,否则它通常不值得麻烦,即使你永远不会自己做)。