Когда я запускаю 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 имеют такие подводные камни и имеют деструктивные действия, которые выполняются молча, если пользователь не знает о таком поведении?
Ааа это имеет смысл. поэтому во втором случае он переименовывает tempfile1 в tempfile2, оставляя содержимое tempfile1 нетронутым, в то время как молча «переписывает» tempfile2, поскольку имя файла уже существует?
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, которая запрашивает подтверждение перед перезаписью файлов; или используйте псевдоним, чтобы сделать это значение по умолчанию.
*
в этом контексте является расширением имени файла оболочки. В первом примере он заменяется на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
.