我在 Windows 10 机器上使用 Ubuntu。我尝试重命名 5 个文件 (file1.txt、file2.txt、file3.txt、file4.txt、file5.txt),以便每个文件都替换为 Sample#_VoucherID.fastq.gz。
为此,我有一个 .csv 文件,其格式为oldfile,newfile
,我的使用方法sed
如下”
sed 's/^/mv -vi /;s/,/ /;s/$//' < File-Rename.csv | bash -e
每当我运行这个程序时,我都不会得到:
Sample#_VoucherID.fastq.gz
对于每个文件,我得到的'Sample#_VoucherID.fastq.gz'$'\r'
都是。为什么会发生这种情况?如果我mv
在 Ubuntu 终端中使用 just 来重命名文件,我会得到我想要的重命名文件,而文件名前后没有'
、和 。如果我不在文件中使用 并删除引号,它会打印:$
\
| bash -e
mv -vi file1.txt Sample1_VoucherID.fastq.gz
mv -vi file2.txt Sample2_VoucherID.fastq.gz
mv -vi file3.txt Sample3_VoucherID.fastq.gz
mv -vi file4.txt Sample4_VoucherID.fastq.gz
mv -vi file5.txt Sample5_VoucherID.fastq.gz
但是,它实际上并没有运行该mv
命令。如何重命名文件而不产生这些多余的字符?
答案1
发生这种情况是因为您的输入文件File-Rename.csv
具有 Windows 样式的 CRLF 行结尾而不是 Unix 样式LF
- 这$'\r'
是 shell 表示回车符的方式。
s/$//
您可以通过将最终的 sed 表达式从(实际上不执行任何操作 -$
在正则表达式中是一个与行尾匹配的零长度断言,但实际上并不消耗字符)更改为来“更正”命令s/\r$//
或者,使用以下方式转换输入文件dos2unix
但是这种重命名文件的方法存在问题 - 特别是,如果新旧名称包含空格或某些 shell 特殊字符,则重命名会失败 - 甚至允许代码注入1。我建议使用类似
while IFS=, read old new; do
mv -vi -- "$old" "$new"
done < <(sed 's/\r$//' File-Rename.csv)
或者
while IFS=, read old new; do
echo mv -vi -- "$old" "${new%$'\r'}"
done < File-Rename.csv
(echo
一旦您对建议的命令满意,请删除)。
请注意,对于 CSV 格式中合法的某些名称(特别是包含带引号的嵌入逗号的名称,"foo,bar",baz
例如),这种方法本身会失败。
1 想想如果有人输入一个文件名会发生什么,foo;rm *
例如