为什么使用 sed 和 mv 重命名文件会打印 '$'\r'

为什么使用 sed 和 mv 重命名文件会打印 '$'\r'

我在 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 *例如

相关内容