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
) с двойными кавычками ("
Вы не должны избегать этих специальных символов. Таким образом, у вас есть два варианта:
Полностью удалите следующее назначение:
then # line=$(echo $line | sed 's/\[/\\[/g' | sed 's/\]/\\]/g')`
или же
Удалите двойные кавычки в следующей строке:
mv $line "Grisaia_no_Kajitsu_${EP}.mkv"
Дальнейшие соображения
Разбор вывода
ls
это никогда не хорошая идея Подумайте о именах файлов с пробелами. Смотрите этот документ для получения дополнительной информации.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