我是 Linux 新手sed
,awk
但我不介意挑战自己的新想法。话虽这么说,我了解 的目的以及如何使用rename
和sed
来处理常见事件,例如从所有文件中添加$date
或删除 a 。_1234
但是,我想弄清楚如何重命名 100 个除了文件类型之外彼此没有关系的文件。
重命名示例:
- 旧名称 alpha.ai 更名为 omega.ai
- 旧名称pie32.ai更名为apple.ai
- 旧名称 xmas.ai 更名为 santa.ai
我最初使用 bash 脚本将所有名称提取到 .csv 文件并将它们放置在 A 列中。在 BI 列中写入新名称。现在,由于没有发生常见事件,您如何编写sed
或类似的内容来做到这一点?
#!/bin/bash
for i in *.ai
do
mv $i $(echo $i | sed "a1,b1")
done
答案1
如果您碰巧有一个如下所示的文件:
old_name1, new_name1
old_name2, new_name2
old_name3, new_name3
你可以做一个肮脏的小把戏:
sed 's/^/mv -vi "/;s/, /" "/;s/$/";/' < names.csv | bash -
sed comamnds(以分号分隔)执行此操作(s
用于替换,/
用作分隔符,任何其他字符都可以,@
也经常使用):
s/^/mv -vi "/
mv -vi "
-在每行的开头添加(^
是行的开头);s/, /" "/
- 将逗号后跟空格替换为" "
;s/$/";/
- 将双引号附加到所有行($
表示行尾)
因此 的输出sed
将是这样的:
mv -vi "old_name1" "new_name1"
mv -vi "old_name2" "new_name2"
mv -vi "old_name3" "new_name3"
将被送入bash
执行。文件名周围的引号不是强制性的,它们只是保护文件名中任何可能的空格(但是它们肯定不会帮助防止逗号后面的空格,因为它被用作分隔符)。指示显示它正在做什么(如果出现问题,您会知道发生了什么),将导致-v
它询问是否要覆盖已经存在的文件。mv
-i
答案2
您的脚本中有几个引用问题。它将破坏包含特殊字符的文件名:空格、\[?*-
.
**始终在变量替换"$i"
和命令替换周围使用双引号"$(sed …)".
。如果没有双引号,变量的值将被解释为以空格分隔的通配符模式列表,并且每个模式都由匹配的文件名列表替换(如果没有匹配项,则模式保持不变)。
另外,如果文件名以 开头-
,它将被解释为选项 by ,mv
也可能被 解释为选项echo
。首先传递--
告诉命令不会有更多的选项。
for i in *.ai; do
mv -- "$i" "$(printf '%s\n' "$i" | sed 's,a1,b1,')"
done
(这仍然假设您的文件名不包含换行符。)(我还将参数固定sed
为您可能的意思。)
如果文件名列表是简单的逗号分隔且不带引号,则可以使用 shell 脚本对其进行解析。这假设任何文件名中都没有逗号或换行符。
while IFS=, read -r from to junk; do
mv -- "$from" "$to"
done <"$files_to_rename.csv"
如果您的输入文件是可能引用的 CSV 文件,请使用真正的 CSV 解析器。不要尝试自己推出。看有没有强大的命令行工具来处理 csv 文件?例如,在 Python 中(在标准输入上使用 CSV):
import csv, os, sys
for line in csv.reader(sys.stdin):
(source, dest) = line
os.rename(source, dest)
答案3
如果您的文件有有趣的字符('
、"
、\
、$
),您可以循环该文件并将其读入 bash 数组。
while IFS=, read -r -a arr; do mv "${arr[@]}"; done <files.csv
答案4
当遇到这类问题时,我通常会手动使用 sed/bash 技巧。
- 我要么编写一个编辑器宏,要么编写一个愚蠢的小程序,读取 csv 文件并写入“mv file1 file2”形式的行。
- 然后我运行脚本(或宏)并将输出保存到 run-my-cmds.sh
- 目视检查 run-my-cmds.sh 以确保其正确
- bash 运行我的cmds.sh