【问题标题】:Read & Remove files containing space in its name读取和删除名称中包含空格的文件
【发布时间】:2019-10-15 12:58:46
【问题描述】:

我必须从文件 A.txt 中读取文件名列表,其中文件名中有空格,所以无法删除。文件 A.txt 如下所示

20150726140135_Content 1.mp4
20150726162955_Content 1.mp4
20150726163056_Content 3.mp4
20150726164057_Content 5.mp4
20150726170315_Tab main 2.mp4

for f in $(cat A.txt) ; do 
   rm "/tmp/$f";
done

虽然尝试这个文件分成两个导致错误

rm: cannot remove `/tmp/20150726170315_Tab': No such file or directory
rm: cannot remove `/tmp/2': No such file or directory

【问题讨论】:

    标签: linux shell unix sh


    【解决方案1】:

    $(cat) 中的 i

    是 bash 中常见的反模式。您不应该使用 for 循环来读取行。这不起作用,因为:

    1. 第一个 $(cat A.txt) 扩展为 20150726140135_Content 1.mp4 20150726162955_Content 1.mp4 20150726163056_Content 3.mp4 20150726164057_Content 5.mp4 20150726170315_Tab main 2.mp4(无引号)。

    2. 然后shell执行命令for i in 20150726140135_Content 1.mp4 20150726162955_Content 1.mp4 20150726163056_Content 3.mp4 20150726164057_Content 5.mp4 20150726170315_Tab main 2.mp4。换行符和空格被解释为参数分隔符。

    read a file line by line in bash 使用while IFS= read -r 循环:

    while IFS= read -r f; do 
       rm "/tmp/$f";
    done < A.txt
    

    【讨论】:

      【解决方案2】:

      您可以使用 xargs。 -I' 将使用基于行的输入。

      xargs -i{} rm /tmp/{} < file.txt
      

      【讨论】:

      • 我认为应该是/tmp/{}。并且可能使用-d$'\n' 作为xargs 默认解释引号,所以如果文件名有引号,它将失败。
      【解决方案3】:

      如果您想删除从 2015 年开始的文件或任何其他模式

      while IFS='\s' read -r f; do 
         rm $f*;
      done
      

      【讨论】:

      • 这个答案至少有 4 个问题。 IFS 接受字符的文字列表,而不是模式。 \s 不是代表bash 中的空格的模式。设置IFS 的唯一目的是指定如何拆分输入行,但read 不会进行任何拆分,因为它只有一个参数。一旦您确实f 中有一个文件名,不加引号的$f 只会重复相同的分词问题。
      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-30
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多