mv: не может быть статистика - нет такого файла или каталога

Я передал вывод команды 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: невозможно настроить '\ [Chihiro \] _ Grisaia_no_Kajitsu_-01\ [1920x816_Blu-ray_FLAC \] \ [D2B961D6 \]. mkv': такого файла или каталога нет

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

1 ответ

Решение

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

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

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

    или же

  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
Другие вопросы по тегам