Является ли mv * деструктивной командой для каталога с 2 или более файлами? Какие другие команды Linux имеют подобное поведение?

Когда я запускаю mv * без целевого каталога в каталоге, скажем, с 10 файлами, я получаю следующее сообщение об ошибке

root@tryit-apparent:~/test2# ls                                                                                                                        
file1.txt  file10.txt  file2.txt  file3.txt  file4.txt  file5.txt  file6.txt  file7.txt  file8.txt  file9.txt                                          
root@tryit-apparent:~/test2# mv *                                                                                                                      
mv: target 'file9.txt' is not a directory       

Когда я запускаю его в каталоге с двумя файлами, он перезаписывает файл одним файлом.

root@tryit-apparent:~/test# ls                                                                                                                         
tempfile  tempfile2                                                                                                                                    
root@tryit-apparent:~/test# mv *                                                                                                                       
root@tryit-apparent:~/test# ls                                                                                                                         
tempfile2                                

Я читал справочные страницы, но не мог понять этого поведения. Хотели бы знать, что вызывает такое поведение и что происходит под капотом?

Какие еще команды Linux имеют такие подводные камни и имеют деструктивные действия, которые выполняются молча, если пользователь не знает о таком поведении?

* в этом контексте является расширением имени файла оболочки. В первом примере он заменяется на mv file1.txt file10.txt file2.txt file3.txt file4.txt file5.txt file6.txt file7.txt file8.txt file9.txt, что не является допустимой командой mv. Второй пример расширяется до mv tempfile1 tempfile2.
kaylum 21.12.2020 06:04

Ааа это имеет смысл. поэтому во втором случае он переименовывает tempfile1 в tempfile2, оставляя содержимое tempfile1 нетронутым, в то время как молча «переписывает» tempfile2, поскольку имя файла уже существует?

elixir 21.12.2020 06:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
118
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Move предназначен для перемещения или переименования файла или каталога, поэтому вам нужен source и место назначения.

Если путь к файлу неизменен, это становится операцией переименования.

Если путь меняется, а имя остается прежним, это перемещение.

Вы можете сделать это, изменив путь и имя.

Справочные страницы могут быть сложными для понимания.

Погуглите, может поможет: https://www.howtoforge.com/linux-mv-command/

На мой взгляд, вы могли бы выполнить операцию cp, за которой следует rm, чтобы добиться аналогичных результатов, но это два шага, а не один.

Ответ принят как подходящий

В Unix, в отличие от некоторых других операционных систем, подстановочные знаки, такие как *, расширяются оболочкой перед тем, как будут переданы выполняемой команде. Поэтому, когда вы запускаете mv * с tempfile и tempfile2 в качестве единственных файлов в текущем каталоге, на самом деле оболочка выполняет mv tempfile tempfile2, который, как обычно, переименовывает первый файл поверх второго, стирая предыдущее содержимое tempfile2. Оболочка не знает и не заботится о том, чтобы эта команда специально обрабатывала свой последний аргумент, и mv не может знать, что два ее аргумента получены из расширения с подстановочными знаками. Отсюда и поведение, которое вы видите.

У вас могут быть похожие проблемы даже с более чем двумя файлами. Например, если у вас есть файлы с именами от tempfile1 до tempfile9 и подкаталог с именем zyzzx, то mv * переместит все ваши временные файлы в подкаталог zyzzx.

В основном вам просто нужно знать, как работают подстановочные знаки, и проявлять осторожность с командами, которые специально обрабатывают один из своих аргументов (например, как место назначения). cp — еще один, на который стоит обратить внимание по той же причине. Для интерактивного использования вы можете привыкнуть к использованию опции -i для mv и cp, которая запрашивает подтверждение перед перезаписью файлов; или используйте псевдоним, чтобы сделать это значение по умолчанию.

Другие вопросы по теме