mv:无法统计 - 没有此类文件或目录

时间:2017-09-01 01:26:17

标签: bash file-rename mv nosuchfileexception

我已将ls命令的输出传送到文件中。 The contents就像这样:

[Chihiro]_Grisaia_no_Kajitsu_-_01_[1920x816_Blu-ray_FLAC][D2B961D6].mkv
[Chihiro]_Grisaia_no_Kajitsu_-_02_[1920x816_Blu-ray_FLAC][38F88A81].mkv
[Chihiro]_Grisaia_no_Kajitsu_-_03_[1920x816_Blu-ray_FLAC][410F74F7].mkv

我尝试根据剧集编号重命名这些剧集如下:

cat grisaia | while read line; 
   #get the episode number
   do EP=$(echo $line | egrep -o  "_([0-9]{2})_" | cut -d "_" -f2)
   if [[ $EP ]]
      #escape special characters
      then line=$(echo $line | sed 's/\[/\\[/g' | sed 's/\]/\\]/g')
      mv "$line" "Grisaia_no_Kajitsu_${EP}.mkv"
   fi
done

mv命令以代码1退出,出现以下错误:

  

mv:不能统计   ' \ [千寻\] _ Grisaia_no_Kajitsu _- 01 \ [1920x816_Blu-ray_FLAC \] \ [D2B961D6 \] MKV&#39 ;:   没有这样的文件或目录

我真正不知道的是,如果我复制的文件不是stat并尝试统计文件,那么它就可以了。我甚至可以使用与输出完全相同的字符串并单独执行mv命令。

1 个答案:

答案 0 :(得分:2)

如果用双引号($line)包围变量("),则不需要转义这些特殊字符。所以你有两个选择:

  1. 完全删除以下分配:

    then # line=$(echo $line | sed 's/\[/\\[/g' | sed 's/\]/\\]/g')`
    

  2. 删除以下行中的双引号:

    mv $line "Grisaia_no_Kajitsu_${EP}.mkv"
    
  3. 进一步考虑

    1. 解析ls的输出绝不是一个好主意。考虑带空格的文件名。有关详细信息,请参阅this document

    2. 这里不需要cat

      cat grisaia | while read line; 
          ...
      done
      

      使用它来避免不必要的管道:

      while read line; 
          ...
      done < grisaia
      
    3. 为什么在某些情况下避免管道是好的? (回答评论)

      管道创建子壳(价格昂贵),你也可以犯下以下错误:

      last=""
      
      cat grisaia | while read line; do
          last=$line
      done
      
      echo $last # surprise!! it outputs an empty string
      

      原因是循环中的$last属于另一个子shell。

      现在,看看管道的相同方法:

      while read line; do
          last=$line
      done < grisaia
      
      echo $last # it works as expected and prints the last line