Команда like mv foo* ~/bar/
выдает это сообщение в stderr, если не найдено ни одного файла foo*
.
mv: cannot stat `foo*': No such file or directory
Тем не менее, в сценарии, над которым я работаю, этот случай вполне подойдет, и я хотел бы опустить это сообщение в наших журналах.
Есть ли хороший способ сказать, mv
чтобы быть тихим, даже если ничего не было перемещено?
mv foo* ~/bar/ 2> /dev/null
?mv
. :) Но это будет делать, конечно.mv
реализации поддерживают-q
опцию, чтобы успокоить их, но это не является частью спецификации POSIX дляmv
.mv
В GNU Coreutils, например, вовсе не имеют такой вариант.Ответы:
Вы ищете это?
источник
set -e
(который должен использоваться в каждом сценарии оболочки) потерпит неудачу. Вы можете добавить,|| true
чтобы отключить проверку для одной команды.set -e
не следует использовать в каждом сценарии оболочки, во многих случаях это делает управление ошибками еще более сложным, чем без него.На самом деле, я не думаю, что отключение звука
mv
является хорошим подходом (помните, что он может сообщать вам и о других вещах, которые могут представлять интерес ... например, отсутствующие~/bar
). Вы хотите отключить звук только в том случае, если ваше глобальное выражение не возвращает результатов. На самом деле, а не выполнять его вообще.Не выглядит очень привлекательно, и работает только в
bash
.ИЛИ ЖЕ
только кроме вас в
bash
сnullglob
набором. Вы платите цену за 3-хкратное повторение образца шара.источник
foo*
если он является единственным в текущем каталоге, который соответствует глобуfoo*
. Это можно обойти с помощью выражения glob, которое буквально не соответствует самому себе. Например[ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/
.find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/
- GNU
mv
имеет хороший параметр "destination first" (-t
) иxargs
может пропустить выполнение своей команды, если нет ввода вообще (-r
). Использование-print0
и-0
соответственно гарантирует, что не будет беспорядка, когда имена файлов содержат пробелы и другие "забавные" вещи.источник
-maxdepth
,-print0
,-0
и-r
также GNU расширения (хотя некоторые из них находятся в других реализациях в настоящее время).mv
.Важно понимать, что на самом деле это оболочка, которая расширяет ее
foo*
до списка совпадающих имен файлов, поэтому мало чтоmv
может сделать сам.Проблема здесь в том, что когда глобус не совпадает, некоторые оболочки
bash
(и большинство других подобных Борну оболочек, такое ошибочное поведение было фактически введено оболочкой Борна в конце 70-х) дословно передают шаблон в команду.Таким образом, здесь, когда
foo*
не совпадает ни один файл, вместо прерывания команды (как это делают оболочки до Борна и несколько современных оболочек), оболочка передает дословныйfoo*
файлmv
, поэтому в основном запрашиваетсяmv
перемещение вызываемого файлаfoo*
.Этот файл не существует. Если бы это было так, это действительно соответствовало бы шаблону, поэтому
mv
выдает ошибку. Если шаблон былfoo[xy]
вместо этого,mv
мог бы случайно переместить файл с именемfoo[xy]
вместоfoox
иfooy
файлов.Теперь, даже в тех оболочках, у которых нет этой проблемы (pre-Bourne, csh, tcsh, fish, zsh, bash -O failglob), вы все равно получите сообщение об ошибке
mv foo* ~/bar
, но на этот раз от оболочки.Если вы хотите считать это не ошибкой, если нет соответствия файлов
foo*
и в этом случае ничего не перемещать, сначала нужно создать список файлов (таким образом, чтобы не вызывать ошибку, например, с помощьюnullglob
параметра некоторые снаряды), и тогда только вызовmv
это список не пустой.Это было бы лучше, чем скрывать все ошибки
mv
(как при добавлении2> /dev/null
), как если бы произошелmv
сбой по любой другой причине, вы, вероятно, все равно захотите узнать, почему.в зш
Или используйте анонимную функцию, чтобы избежать использования временной переменной:
zsh
это одна из тех оболочек, которые не имеют ошибки Борна и сообщают об ошибке, не выполнив команду, когда глобус не совпадает (иnullglob
опция не была включена), поэтому здесь вы можете скрытьzsh
ошибку и восстановить для stderr,mv
так что вы все равно увидитеmv
ошибки, если они есть, но не ошибки о несоответствующих глобусах:Или вы можете использовать,
zargs
что также позволит избежать проблем, еслиfoo*
глобус будет расширяться до слишком больших файлов.В кш93:
В Баш:
bash
не имеет синтаксиса для включения толькоnullglob
для одного глобуса, иfailglob
опция отменяется,nullglob
поэтому вам понадобятся такие вещи, как:или установить параметры в подоболочке для сохранения, чтобы сохранить их до, а затем восстановить их.
В
yash
В
fish
В оболочке fish поведение nullglob является значением по умолчанию для
set
команды, поэтому оно просто:POSIXly
Там нет
nullglob
опции в POSIXsh
и нет массива, кроме позиционных параметров. Есть способ, который вы можете использовать для определения соответствия шара или нет:Используя как a, так
foo[*]
иfoo*
glob, мы можем различить случай, когда нет соответствующего файла, и случай, когда есть один файл, который вызванfoo*
(чтоset -- foo*
не может сделать).Больше чтения:
источник
Возможно, это не самый лучший вариант, но вы можете использовать
find
команду, чтобы проверить, пуста ли папка или нет:источник
foo*
путь поискаfind
.Я предполагаю, что вы используете bash, потому что эта ошибка зависит от поведения bash для расширения непревзойденных глобусов для себя. (Для сравнения, zsh выдает ошибку при попытке развернуть бесподобный глобус.)
Итак, как насчет следующего обходного пути?
Это будет молча игнорировать,
mv
если происходитls -d foo*
сбой, в то время как все еще регистрирует ошибки, еслиls foo*
успешно, но происходитmv
сбой. (Остерегайтесь,ls foo*
может произойти сбой по другим причинам, кромеfoo*
несуществующих, например, из-за недостаточных прав, проблем с FS и т. Д., Поэтому такие условия будут игнорироваться этим решением.)источник
bash
). +1 за то, что учли тот факт, чтоmv
может не получиться по другим причинам, кромеfoo*
несуществующих.ls
команды будет не очень понятен для будущих читателей, по крайней мере, без комментариев.)ls -d foo*
может возвращаться с ненулевым статусом выхода и по другим причинам, например после aln -s /nowhere foobar
(по крайней мере, в некоторыхls
реализациях).Вы можете сделать, например,
mv 1>/dev/null 2>&1 foo* ~/bar/
или жеmv foo* ~/bar/ 1&>2
Для получения более подробной информации смотрите: http://mywiki.wooledge.org/BashFAQ/055
источник
mv foo* ~/bar/ 1&>2
не заставляет команду замолчать, она отправляет то, что было бы на stdout, на stderr./dev/null
наNUL
1
и2
что?Вы можете обмануть (переносимо) с
perl
:источник
Если вы собираетесь использовать Perl, вы можете пройти весь путь:
или как однострочник:
(Подробнее о
move
команде см. Документацию для File :: Copy .)источник
Вместо
ты можешь сделать
Просто, читабельно :)
источник
cp
ниrm
молчать, еслиfoo*
не существует.Является ли команда «Выше» успешной или нет, мы можем определить по состоянию выхода предыдущей команды
если вывод echo $? отличается от 0 означает, что команда неуспешна, если вывод равен 0 означает, что команда успешна
источник