ошибка bash при переименовании файлов с пробелами - цель mv не является каталогом

Я пытаюсь переименовать кучу файлов, содержащих пробелы, избавляясь от пробелов. Я думал, что нашел правильную команду bash:

for f in *.txt; do mv \"$f\" ${f/ /}; done

Однако это дает ошибку «mv: target не является каталогом» для каждого файла. Если я заменю «mv» на «echo mv» в команде, он напечатает правильную команду mv для каждого файла, и если я наберу любую из этих команд mv по отдельности, они будут работать. Например, если у меня есть 2 файла, «a.txt» и «b.txt», и я запускаю приведенную выше команду, я получаю:

mv: target 'a.txt' is not a directory
mv: target 'b.txt' is not a directory

Если я наберу команду:

for f in *.txt; do echo mv \"$f\" ${f/ /}; done

Я получил:

mv "a .txt" a.txt
mv "b .txt" b.txt

Я нашел другой способ сделать это, используя «переименовать», но я хотел бы знать, почему это не работает.


person Jim Hines    schedule 23.10.2014    source источник
comment
Мне интересно, как вы ставите пробелы перед .txt, потому что он этого не примет. Он будет думать, что .txt не является каталогом   -  person KRUKUSA    schedule 23.10.2014


Ответы (2)


Пытаться:

for f in *.txt; do mv "$f" "${f// /}"; done

Три пункта:

  1. Кавычки вокруг переменной оболочки не должны экранироваться.

  2. В общем, рекомендуется заключать в двойные кавычки каждую ссылку на переменную оболочки.

  3. ${f/ /} удаляет только первое вхождение пробела. Чтобы удалить все пробелы, используйте ${f// /}.

Что пошло не так

$ touch {a,b}" .txt"
$ ls *.txt
a .txt  b .txt
$ for f in *.txt; do mv \"$f\" ${f/ /}; done
mv: target `a.txt' is not a directory
mv: target `b.txt' is not a directory

Выражение \"$f\" не ведет себя так, как будто оно заключено в двойные кавычки. Он расширяется до двух аргументов, таких как "a и .txt", где двойные кавычки обрабатываются как обычные символы, точно так же, как a является обычным символом. Поскольку у mv есть три аргумента ("a и .txt" и a.txt), mv считает, что вы пытаетесь переместить первые два аргумента в третий, а третий должен быть каталогом. Поскольку третий не является каталогом, он выдает сообщение об ошибке.

person John1024    schedule 23.10.2014
comment
Есть ли способ сохранить пробелы? И еще, переименовать файл? Я получаю mv: target ‹Transparent-300-400.png› не каталог, а полное имя файла Jam Banner Transparent.png, я беру имя, добавляю размер и переименовываю его, но все равно эта ошибка . Файлы с _ вместо пробелов переименовываются, как и ожидалось. Я ожидаю, что это будет Jam Banner Transparent-300-400.png - person Candid Moon _Max_; 01.06.2017
comment
@CandidMoon Если вы получаете сообщение не о каталоге, это, вероятно, означает, что переменные оболочки не были заключены в двойные кавычки. Конечно, не зная, что именно вы делаете, я могу только догадываться. - person John1024; 01.06.2017
comment
ideone.com/yQaViz это мой код, я использую imagemagick и cowsay. Я знаю, что было бы лучше, если бы я создал новый вопрос об этом из-за баллов, хотя спасибо за ответ. - person Candid Moon _Max_; 01.06.2017
comment
Я вижу: convert $fullfilename -resize ${new_width_height[0]}x${new_width_height[1]} $new_file_name Если имена файлов содержат пробелы, они должны быть заключены в двойные кавычки. - person John1024; 02.06.2017
comment
Это должен быть принятый ответ - person hoistyler; 02.07.2021

Поскольку это первое, что появилось в гугле при поиске этой ошибки, я решил немного добавить.

Эта ошибка возникает, если у вас есть более двух аргументов и последний результат не является каталогом.

Это работает (когда output.txt не существует):

mv file1.txt output.txt

Это не так (если файл2.txt существует):

mv file1.txt file2.txt

В моем случае я делал: mv prefix_* output_file_name чтобы убедиться, что у загруженного файла было согласованное имя, но в каталоге появился другой файл, повторение в цели mv не является ошибкой каталога

person sdfgeoff    schedule 25.01.2019
comment
похоже, у вас есть 2 аргумента после mv в обоих случаях .. что мне не хватает? - person yano; 21.05.2021
comment
Верно. Я только что уточнил, что в одном случае файл не существовал, а в другом существовал. - person sdfgeoff; 28.05.2021