想要弄一个自动定时把下载下来的动画重命名并移动到相应目录的脚本
原名大概是这样
想命名成类似 S01E10.mp4 这样
于是建了一个试验目录和几个叫 测试 01 [TEST].txt 这种文件名的文件
紧接着就遇到了第一个问题,grep 好像不支持 \d 转义,无法匹配到数字序号。这个简单,用 [0-9] 代替即可。
然后就按照一些博客写的,用 for … in … 来循环,结果如下
rafom@rfm-main-win:~/playground$ for f in $(ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt'); do echo $f ; done
测试
01
[TEST].txt
测试
02
[TEST].txt
测试
03
rafom@rfm-main-win:~/playground$
可以看到原文件名被拆开了。查了一下发现 for … in … 是以空格、制表符、换行符等特殊字符作为分隔的(而不是只以换行符作为分隔)
这样显然不行。于是又查了些资料,换用 while read line 实现
rafom@rfm-main-win:~/playground$ ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do echo $line; done
测试 01 [TEST].txt
测试 02 [TEST].txt
测试 03 [TEST].txt
rafom@rfm-main-win:~/playground$
这样看起来没问题了。接下来是重命名的部分,用 sed 命令操作字符串
这里我不知道“删除”部分字符串的参数,于是用了个大概不是正道的办法,用空内容去替换
rafom@rfm-main-win:~/playground$ ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do echo $line | sed -e 's/测试 /S01E/' -e 's/ \[TEST\]//'; done
S01E01.txt
S01E02.txt
S01E03.txt
rafom@rfm-main-win:~/playground$
看起来也没问题。接下来加入文件操作命令(为了减少失败后的操作量,这里暂时用 cp 代替 mv)
rafom@rfm-main-win:~/playground$ ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do cp $line ./test/$(echo $line | sed -e 's/测试 /S01E/' -e 's/ \[TEST\]//'); done
cp: target './test/S01E01.txt' is not a directory
cp: target './test/S01E02.txt' is not a directory
cp: target './test/S01E03.txt' is not a directory
rafom@rfm-main-win:~/playground$
果不其然失败了……但是这个提示很奇怪:’./test/S01E01.txt’ 不是目录?当然不是,它应该是文件名啊!查了一下没找到强制定义为文件名的方法,也就说明这里不是少了参数的原因。又想了一下,发现可能是源文件的部分在同一行里输入了多个值,也就是说变成了把多个文件复制到一个文件夹的操作,从而导致这个报错。
$line 那里输入的是“测试 01 [TEST].txt”这样的文件名,看起来是因为这里没有作为一个字符串整体输入进 cp 的第一个参数。那么给它加个引号行不行呢?
rafom@rfm-main-win:~/playground$ ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do cp '$line' ./test/$(echo $line | sed -e 's/测试 /S01E/' -e 's/ \[TEST\]//'); do
ne
cp: cannot stat '$line': No such file or directory
cp: cannot stat '$line': No such file or directory
cp: cannot stat '$line': No such file or directory
rafom@rfm-main-win:~/playground$
还是不行……’$line’看起来是没有引用出变量,而是直接作为一个字符串输入到 cp 里了……那到底怎么办呢?实在想不出办法了,破罐破摔,把单引号改成双引号
rafom@rfm-main-win:~/playground$ ls | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do cp "$line" ./test/$(echo $line | sed -e 's/测试 /S01E/' -e 's/ \[TEST\]//'); done
rafom@rfm-main-win:~/playground$
什么?竟然成功了?进到 test 目录里看,想要的文件果然出现了
把文件删了,给测试用的源文件里编辑一些内容,然后把命令里的 cp 换成 mv,为了放进定时脚本再加上绝对路径
rafom@rfm-main-win:~/playground$ ls /home/rafom/playground | grep -e '测试 [0-9][0-9] \[TEST\]\.txt' | while read line; do mv /home/rafom/playground/"$line" /home/rafom/playground/test/$(echo $line | sed -e 's/测试 /S01E/' -e 's/ \[TEST\]//'); done
rafom@rfm-main-win:~/playground$
成功!虽然不知道为什么单引号不行但双引号可以,总之是成功了!
bash 对我等绿皮来说还是太难了