mv: Cannot stat - Нет такого файла или каталога

Я отправил вывод команды ls в файл. Содержимое выглядит следующим образом:

[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': нет такого файла или каталога

Чего я действительно не понимаю, так это того, что если я скопирую файл, который не может быть статистическим, и попытаюсь выполнить его стат, он сработает. Я даже могу взять ту же самую строку, которая выводится, и индивидуально выполнить команду mv.


person jacob    schedule 01.09.2017    source источник


Ответы (1)


Если вы заключите переменную ($line) в двойные кавычки ("), вам не нужно экранировать эти специальные символы. Итак, у вас есть два варианта:

  1. Полностью удалите следующее назначение:

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

    or

  2. Удалите двойные кавычки в следующей строке:

    mv $line "Grisaia_no_Kajitsu_${EP}.mkv"
    

Дальнейшие соображения

  1. Анализировать вывод ls - никогда не лучшая идея. Подумайте о именах файлов с пробелами. Дополнительную информацию см. В этом документе.

  2. cat здесь не нужен:

    cat grisaia | while read line; 
        ...
    done
    

    Используйте это вместо этого, чтобы избежать ненужной трубы:

    while read line; 
        ...
    done < grisaia
    

Почему в некоторых сценариях лучше избегать труб? (отвечая на комментарий)

Трубы создают подоболочки (которые стоят дорого), и вы также можете сделать следующие ошибки:

last=""

cat grisaia | while read line; do
    last=$line
done

echo $last # surprise!! it outputs an empty string

Причина в том, что $last внутри цикла принадлежит другой подоболочке.

Теперь рассмотрим тот же подход без труб:

while read line; do
    last=$line
done < grisaia

echo $last # it works as expected and prints the last line
person whoan    schedule 01.09.2017
comment
Спасибо за Ваш ответ! Есть ли действительно существенная разница между cat и ‹в функциональном отношении? Кажется, это просто предпочтение - person jacob; 01.09.2017
comment
Я добавил к ответу дополнительную информацию о трубах. - person whoan; 01.09.2017
comment
Это в значительной степени покрывает это. - person David C. Rankin; 01.09.2017
comment
Очень качественный ответ. Спасибо - person jacob; 01.09.2017