Как & ldquo; mv * & rdquo; знаете, куда двигаться?

Если вы хотите спасти статус своей системы и не удалить вещь, попробуйте использовать диск для восстановления: Boot repair disk

Это помогло мне во многих ситуациях, подобных этим, возможно, может восстановить ваши вещи. Попробуйте сначала, прежде чем пытаться удалить что-то, что вам, возможно, не нужно ...

2
задан 17 September 2017 в 09:17

4 ответа

Когда вы запустили его в этом каталоге, mv * был эквивалентен mv 1 2 3 4 a b c. Если параметр -t не присутствует, mv рассматривает последний аргумент без опции в качестве имени пункта назначения и, таким образом, перемещается 1, 2, 3, 4, a и b все в c.

Оболочка расширяет * в список имен файлов. Когда это произойдет, команда, которую вы запускаете, на самом деле не видит *, а только то, что она расширила. Таким образом, команда, которую вы запускаете, не может судить о том, как обрабатывать ее аргументы на основе того, что вы на самом деле набрали, - она ​​видит только, что оболочка передает ей.

Когда вы запускаете mv * - что, как вы, вероятно, предположили, что почти всегда следует избегать - оболочка, а не команда mv сама расширяет * в , расширяет список всех файлов и каталогов, содержащихся в текущем каталоге, за исключением любых чьи имена начинаются с ..

(Вы можете настроить, как это работает с помощью опций оболочки dotglob, nullglob и nocaseglob и переменной GLOBIGNORE. Подробнее см. в документации .)

Если c не были каталогом, ваша команда потерпит неудачу, не сдвинет ничего и покажет это сообщение об ошибке:

mv: target 'c' is not a directory

Но так как c был он просто «работал», хотя - если вы выполняли команду для каких-либо целей, кроме как видеть, что она будет делать, вы not должны писать имя отдельного каталога в конец команды после *.

Чтобы более интуитивно показать, почему mv не знает, что его аргументы были расширены из *, предположим, что вы написали:

mv 1 c

Это переместит 1 в c. Но, возможно, вам бы хотелось переместить два элемента в c:

mv 1 2 c

Или пять элементов:

mv 1 2 3 4 a c

Или шесть элементов:

mv 1 2 3 4 a b c

Но оболочка гарантировала, что mv * передал после команде mv как mv 1 2 3 4 a b c.

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

Если вам интересно, что оболочка что-то расширит, вы можете заменить команду, которую вы хотите запустить с помощью printf '%s\n', который печатает все последующие аргументы, переданные ему, разделенные разрывами строк. Например:

printf '%s\n' *
6
ответ дан 18 July 2018 в 06:43

Этот ответ добавляет несколько советов (но я думаю, что главный ответ: @Eliah Kagan).

Я сделал два псевдонима, чтобы сделать вещи немного более безопасными. Я храню их в ~/.bashrc рядом с другими псевдонимами.

alias mv='mv -i' alias rm='rm -i'

Эти псевдонимы делают команды интерактивными, они спрашивают, хотите ли вы перезаписать / удалить.

mv спросите, хотите ли вы переписать цель, если она существует и является файлом, или если цель является каталогом и в ней уже есть файл с тем же именем. Это поможет вам избежать ошибок, например, когда вы используете дикие карты, mv *.

Обратите внимание на

Эти псевдонимы работают только с вашим собственным пользователем Я БЫ. Они не работают с sudo. Если вы хотите, чтобы псевдонимы расширялись после sudo, вы должны установить это отдельно. Если вы хотите, чтобы конкретный псевдоним работал в корневой оболочке (например, вы получили бы от sudo -s или sudo -i), вы должны создать аналогичный псевдоним и сохранить его в /root/.bashrc. Вы можете переопределить псевдонимы (и получить исходное поведение mv и rm) с префиксом «обратная косая черта», \rm filename \mv filename1 filename2 . Вы можете привыкнуть к тому, что флаг -i передается автоматически и имеют ложное представление о например, при запуске другой системы, где эти псевдонимы неактивны.
1
ответ дан 18 July 2018 в 06:43

Когда вы запустили его в этом каталоге, mv * был эквивалентен mv 1 2 3 4 a b c. Если параметр -t не присутствует, mv рассматривает последний аргумент без опции в качестве имени пункта назначения и, таким образом, перемещается 1, 2, 3, 4, a и b все в c.

Оболочка расширяет * в список имен файлов. Когда это произойдет, команда, которую вы запускаете, на самом деле не видит *, а только то, что она расширила. Таким образом, команда, которую вы запускаете, не может судить о том, как обрабатывать ее аргументы на основе того, что вы на самом деле набрали, - она ​​видит только, что оболочка передает ей.

Когда вы запускаете mv * - что, как вы, вероятно, предположили, что почти всегда следует избегать - оболочка, а не команда mv сама расширяет * в , расширяет список всех файлов и каталогов, содержащихся в текущем каталоге, за исключением любых чьи имена начинаются с ..

(Вы можете настроить, как это работает с помощью опций оболочки dotglob, nullglob и nocaseglob и переменной GLOBIGNORE. Подробнее см. в документации .)

Если c не были каталогом, ваша команда потерпит неудачу, не сдвинет ничего и покажет это сообщение об ошибке:

mv: target 'c' is not a directory

Но так как c был он просто «работал», хотя - если вы выполняли команду для каких-либо целей, кроме как видеть, что она будет делать, вы not должны писать имя отдельного каталога в конец команды после *.

Чтобы более интуитивно показать, почему mv не знает, что его аргументы были расширены из *, предположим, что вы написали:

mv 1 c

Это переместит 1 в c. Но, возможно, вам бы хотелось переместить два элемента в c:

mv 1 2 c

Или пять элементов:

mv 1 2 3 4 a c

Или шесть элементов:

mv 1 2 3 4 a b c

Но оболочка гарантировала, что mv * передал после команде mv как mv 1 2 3 4 a b c.

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

Если вам интересно, что оболочка что-то расширит, вы можете заменить команду, которую вы хотите запустить с помощью printf '%s\n', который печатает все последующие аргументы, переданные ему, разделенные разрывами строк. Например:

printf '%s\n' *
6
ответ дан 24 July 2018 в 18:39

Этот ответ добавляет несколько советов (но я думаю, что главный ответ: @Eliah Kagan).

Я сделал два псевдонима, чтобы сделать вещи немного более безопасными. Я храню их в ~/.bashrc рядом с другими псевдонимами.

alias mv='mv -i' alias rm='rm -i'

Эти псевдонимы делают команды интерактивными, они спрашивают, хотите ли вы перезаписать / удалить.

mv спросите, хотите ли вы переписать цель, если она существует и является файлом, или если цель является каталогом и в ней уже есть файл с тем же именем. Это поможет вам избежать ошибок, например, когда вы используете дикие карты, mv *.

Обратите внимание на

Эти псевдонимы работают только с вашим собственным пользователем Я БЫ. Они не работают с sudo. Если вы хотите, чтобы псевдонимы расширялись после sudo, вы должны установить это отдельно. Если вы хотите, чтобы конкретный псевдоним работал в корневой оболочке (например, вы получили бы от sudo -s или sudo -i), вы должны создать аналогичный псевдоним и сохранить его в /root/.bashrc. Вы можете переопределить псевдонимы (и получить исходное поведение mv и rm) с префиксом «обратная косая черта», \rm filename \mv filename1 filename2 . Вы можете привыкнуть к тому, что флаг -i передается автоматически и имеют ложное представление о например, при запуске другой системы, где эти псевдонимы неактивны.
1
ответ дан 24 July 2018 в 18:39

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

Похожие вопросы: