Что делает `mv ./*` без указания места назначения?
27
Я случайно забыл указать пункт назначения перед нажатием клавиши Return. Куда mv ./*без указания места назначения перемещать файлы и каталоги в текущем каталоге?
«Я удивлен, что mvпринимает 1 аргумент» Это не так. Он принимает все аргументы, которые ему передала оболочка после расширения *.
glglgl
Ответы:
41
Если последним аргументом был каталог, вы просто переместили все файлы и каталоги в текущем рабочем каталоге (кроме тех, чьи имена начинаются с точек) в этот каталог. Если было два файла, первый файл мог перезаписать второй файл.
Вот несколько демонстраций:
Более двух файлов и последний аргумент является файлом
$ mkdir d1 d2 d3
$ touch a b c e
$ mv *
mv: target 'e' is not a directory
Более двух файлов и последний аргумент - это каталог
$ mkdir d1 d2 d3
$ touch a b c
$ mv -v *
'a' -> 'd3/a'
'b' -> 'd3/b'
'c' -> 'd3/c'
'd1' -> 'd3/d1'
'd2' -> 'd3/d2'
Два файла
$ touch a b
$ mv -v *
'a' -> 'b'
Дальнейшее объяснение
Оболочка расширяет glob ( *) в аргументы для mv. Глобус обычно расширяется в алфавитном порядке. mvвсегда видит список файлов и каталогов. Он никогда не видит сам шар.
Команда mvподдерживает два типа перемещения. Один есть mv file ... directory. Другой mv old-file-name new-file-name(или mv old-file-name directory/new-file-name).
Сначала я сделаю тестовую базу - 5 файлов и одна папка:
touch file1 file2 file3 file4 file5
mkdir folder
Далее я выполнил тестовую команду. В -vпараметр указывает , что я хочу каждую команду оболочка выполняет быть распечатана в stderr. В -xпараметр указывает , что я хочу того же печатается stderr- но я хочу сделать это после того, как команда вычисляется , но прежде , чем оболочка запускает его.
Итак, вы видите, что команда, которую я передаю оболочке, echo mv *и команда, которую оболочка выполняет после* развертывания, echo mvсопровождаются всеми этими файлами и папкой.
По умолчанию оболочка будет расширять глобусы, такие как:
Поэтому, когда вы запускаете команду в оболочке, настроенной с параметрами по умолчанию, такими mv *как оболочка, расширяет в *слове список аргументов всех файлов в текущем каталоге, отсортированных по локали. Он выполняет системный вызов exec(ve)для mv(по существу) с добавленным списком аргументов. Таким образом, mvполучает все аргументы, поскольку оболочка обрабатывает их и сортирует их. Помимо выполненияstrace чтобы увидеть эти эффекты, вы можете снова использовать отладку, например:
sh -s -- mv * <<\SCRIPT
sed -n l /proc/$$/cmdline
echo "$@"
SCRIPT
По сути, оболочка выполняется mvс содержимым каталога (если он не пустой и не включает файлы / папки с именами, начинающимися с .) в качестве списка аргументов. mvPOSIX указывается, чтобы интерпретировать свой последний аргумент как каталог, если он вызывается с более чем двумя аргументами - таким же образомln это (потому что, на самом деле, они невероятно аналогичные инструменты в основной функции) .
В первой форме резюме mvутилита должна переместить файл, названный операндом source_file, в место назначения, указанное в файле target_file . Эта первая форма краткого обзора предполагается, когда последний операнд не называет существующий каталог и не является символической ссылкой, ссылающейся на существующий каталог. В этом случае, если source_file присваивает имя файлу , не являющемуся каталогом, а target_file заканчивается завершающим /slashсимволом,mv следует рассматривать как ошибку, и операнды source_file обрабатываться не будут.
Во второй форме mvкраткого обзора каждый файл, названный операндом source_file , должен перемещаться в целевой файл в существующем каталоге, названный операндом target_dir , или на который ссылается, если target_dir является символической ссылкой, ссылающейся на существующий каталог. Путь назначения для каждого исходного_файла должен представлять собой конкатенацию целевого каталога, один /slashсимвол, если цель не заканчивается на a /slash, и последний компонент имени пути исходного_файла . Эта вторая форма предполагается, когда последний операнд называет существующий каталог.
Так что, если *расширяется до:
два файла
У вас должен быть только один файл, с первого renamedпо второй после второго unlinked.
один или несколько файлов, за которыми следует каталог или ссылка на него
У вас должен быть только один каталог или ссылка на него, куда только что было перемещено все предыдущее содержимое его родителя.
что-нибудь еще
У вас должно быть сообщение об ошибке и удовлетворительный вздох облегчения.
да, используя старую shштуку, я забыл об отладке с этим, но относительно моего первоначального вопроса, это означает, что проблема не в оболочке mv? Это противно, это проще, чем я думал, но это настоящая ловушка.
user2485710
5
@ user2485710, ключевым моментом является то, что в Unix оболочка отвечает за расширение подстановочных знаков перед передачей аргументов командной строки команде. В Windows каждая команда должна раскрывать шаблоны самостоятельно. Это позволяет оболочкам Unix предлагать расширенные подстановочные знаки, которые работают с любой командой.
CJM
2
@mikeserv, учитывая тот факт, что эти файлы были не так важны, я поспешил привести себя в порядок и перейти к следующему шагу, но я могу подтвердить вещи, как они теперь появляются в моем редактировании моего первого поста / вопроса.
user2485710
6
@mikeserv tl; доктор, *это не единственный аргумент? Правильно? :)
Бернхард
1
@ Бернхард - на самом деле, это один случай, который я не раскрыл - потому что это может быть.
mikeserv
18
Сначала оболочка распространяется ./*на все файлы в текущем каталоге (кроме файлов, начинающихся с точки).
если нет или только один файл: mvтерпит неудачу
если есть два файла: первый перемещается во второй (который, следовательно, теряется)
если есть более двух файлов:
если последний является каталогом: все файлы перемещаются в этот каталог
Спасибо. Как определить, какой подкаталог является «последним»?
Тим
7
Просто позвоните echo ./*и посмотрите, какой порядок использует ваша оболочка (обычно в алфавитном порядке).
Джофель
Если это терпит неудачу с одним файлом, почему это не говорит так?
Ноумен
@ Нумен, я не понимаю ваш комментарий. mvвозвращает сообщение об ошибке, если оно вызывается только с одним аргументом.
17
Вы правы. Та же самая команда из моей истории теперь дает, missing destination file operand after *filename*хотя вчера это не так.
Ноумен
4
Когда вы печатаете mv ./*, ваша оболочка раскроется ./*перед выполнениемmv .
Несколько вещей на заметку:
Если ./*развернуть менее чем в 2 аргумента mv, логически выдаст ошибку.
./* обычно раскрывается в каждый файл (включая каталог), присутствующий в текущем каталоге и не начинающийся с точки.
Вы можете контролировать то, что ./*расширяется, читая документацию вашей оболочки ( man 7 globэто точка входа в тему). У разных оболочек будут разные варианты.
Оболочка расширяет подстановочный знак *до списка содержимого каталога. Затем оболочка передает этот полный список команде. Команда никогда не видит *.
Команда mv file1 file2 ... filen directoryпереместит file1 ... filen в каталог.
пример
Здесь я делаю тестовый каталог, содержащий три файла
$ mkdir t
$ cd t
$ echo a>a; echo b>b; echo c>c
$ ls
a b c
Вы не можете переместить несколько файлов в один файл
$ mv *
mv: target `c' is not a directory
Давайте добавим подкаталог
$ mkdir d
Вы можете переместить несколько файлов в подкаталог
Команда, mv file1 file2 ... filen directoryскорее всего, не имеет ничего общего с *.
mikeserv
@Mike: Мой ответ указывает на то, что последний этап расширения оболочки эффективно превращает последний в первый. Не зная этого, кажется, корень путаницы ОП.
RedGrittyBrick
да, но моя точка оболочка не будет расширяться *в , file dirесли нет какой - то локали , в котором dследует f.
mikeserv
@mikeserv: есть такая локаль, мой пример - это вырезка и вставка из Putty для подключения к системе CentOS 5.6 GNU / Linux.
RedGrittyBrick
какая локаль это? Ваш пример, a b c dкоторый не file ... dir. Я только прокомментировал, потому что вы нигде не упоминаете о сортах и говорите только то, что *становится, file ... dirчего не происходит.
mv
принимает 1 аргумент» Это не так. Он принимает все аргументы, которые ему передала оболочка после расширения*
.Ответы:
Если последним аргументом был каталог, вы просто переместили все файлы и каталоги в текущем рабочем каталоге (кроме тех, чьи имена начинаются с точек) в этот каталог. Если было два файла, первый файл мог перезаписать второй файл.
Вот несколько демонстраций:
Более двух файлов и последний аргумент является файлом
Более двух файлов и последний аргумент - это каталог
Два файла
Дальнейшее объяснение
Оболочка расширяет glob (
*
) в аргументы дляmv
. Глобус обычно расширяется в алфавитном порядке.mv
всегда видит список файлов и каталогов. Он никогда не видит сам шар.Команда
mv
поддерживает два типа перемещения. Один естьmv file ... directory
. Другойmv old-file-name new-file-name
(илиmv old-file-name directory/new-file-name
).источник
Сначала я сделаю тестовую базу - 5 файлов и одна папка:
Далее я выполнил тестовую команду. В
-v
параметр указывает , что я хочу каждую команду оболочка выполняет быть распечатана вstderr
. В-x
параметр указывает , что я хочу того же печатаетсяstderr
- но я хочу сделать это после того, как команда вычисляется , но прежде , чем оболочка запускает его.ВЫХОД
Итак, вы видите, что команда, которую я передаю оболочке,
echo mv *
и команда, которую оболочка выполняет после*
развертывания,echo mv
сопровождаются всеми этими файлами и папкой.По умолчанию оболочка будет расширять глобусы, такие как:
ВЫХОД
Это результат
set [+-]f
функции glob:ВЫХОД
Поэтому, когда вы запускаете команду в оболочке, настроенной с параметрами по умолчанию, такими
mv *
как оболочка, расширяет в*
слове список аргументов всех файлов в текущем каталоге, отсортированных по локали. Он выполняет системный вызовexec(ve)
дляmv
(по существу) с добавленным списком аргументов. Таким образом,mv
получает все аргументы, поскольку оболочка обрабатывает их и сортирует их. Помимо выполненияstrace
чтобы увидеть эти эффекты, вы можете снова использовать отладку, например:ВЫХОД
И переносимо:
ВЫХОД
По сути, оболочка выполняется
mv
с содержимым каталога (если он не пустой и не включает файлы / папки с именами, начинающимися с.
) в качестве списка аргументов.mv
POSIX указывается, чтобы интерпретировать свой последний аргумент как каталог, если он вызывается с более чем двумя аргументами - таким же образомln
это (потому что, на самом деле, они невероятно аналогичные инструменты в основной функции) .Достаточно,
echo
хотя:ВЫХОД
Все файлы были перемещены в последний аргумент - потому что это папка. А что если это не папка?
ВЫХОД
Вот как POSIX
mv
должен вести себя в этом случае:Так что, если
*
расширяется до:два файла
renamed
по второй после второгоunlinked
.один или несколько файлов, за которыми следует каталог или ссылка на него
что-нибудь еще
источник
sh
штуку, я забыл об отладке с этим, но относительно моего первоначального вопроса, это означает, что проблема не в оболочкеmv
? Это противно, это проще, чем я думал, но это настоящая ловушка.*
это не единственный аргумент? Правильно? :)Сначала оболочка распространяется
./*
на все файлы в текущем каталоге (кроме файлов, начинающихся с точки).mv
терпит неудачуmv
не удается.источник
echo ./*
и посмотрите, какой порядок использует ваша оболочка (обычно в алфавитном порядке).mv
возвращает сообщение об ошибке, если оно вызывается только с одним аргументом.missing destination file operand after *filename*
хотя вчера это не так.Когда вы печатаете
mv ./*
, ваша оболочка раскроется./*
перед выполнениемmv
.Несколько вещей на заметку:
./*
развернуть менее чем в 2 аргументаmv
, логически выдаст ошибку../*
обычно раскрывается в каждый файл (включая каталог), присутствующий в текущем каталоге и не начинающийся с точки../*
расширяется, читая документацию вашей оболочки (man 7 glob
это точка входа в тему). У разных оболочек будут разные варианты.источник
Вот короткий ответ:
Оболочка расширяет подстановочный знак
*
до списка содержимого каталога. Затем оболочка передает этот полный список команде. Команда никогда не видит*
.Команда
mv file1 file2 ... filen directory
переместит file1 ... filen в каталог.пример
Здесь я делаю тестовый каталог, содержащий три файла
Вы не можете переместить несколько файлов в один файл
Давайте добавим подкаталог
Вы можете переместить несколько файлов в подкаталог
источник
mv file1 file2 ... filen directory
скорее всего, не имеет ничего общего с*
.*
в ,file dir
если нет какой - то локали , в которомd
следуетf
.a b c d
который неfile ... dir
. Я только прокомментировал, потому что вы нигде не упоминаете о сортах и говорите только то, что*
становится,file ... dir
чего не происходит.