Недавно я удивился, когда сделал что-то подобное
mv ./* ../somedirectory
и обнаружил, что файлы вроде .gitignore
не были перемещены.
Я делаю большую часть своей работы в zsh на OS X, и этот сюрприз укусил меня в bash на CentOS. Я попытался bash на OS X и обнаружил то же поведение: *
не совпадает с точечными файлами. Это кажется мне очень нежелательным, но, видимо, это bash default. (Это может быть тоже zsh по умолчанию, насколько я помню, но я мог изменить его много лет назад в моем .zshrc и забыл, что он когда-либо работал по-другому.)
Как настроить bash так, чтобы он вел себя так, как я ожидал: чтобы * соответствовал всем файлам, а не игнорировал точечные файлы.
Если это вообще неясно, вот как это воспроизвести
cd /tmp
mkdir {t,d}est
touch test/{.,}{1,2,3,4,5,6,7}
ls -hal test
mv test/* dest
ls -hal test # notice dot files are still there
ls -hal dest # notice only some files were mv'ed
Ответы:
удар
Как вы уже заметили, bash не будет соответствовать a
.
в начале имени или косой черты. Чтобы изменить соответствие относительно точки, вы должны установитьdotglob
опцию - man bash :Чтобы включить / настроить его с помощью bash
shopt
, например:Для zsh вы также можете использовать эту
dotglob
опцию, но вы должны будете использоватьsetopt
ее, например:источник
zsh
этом лучший вариант - включить dotglob для каждого отдельного глобуса :mv test/*(D) /dest
Я проверил это, и это решает проблему:
Выход:
источник
*
это шар, который расширяется оболочкой. По умолчанию оболочки не включают файлы, имена которых начинаются с.
(называемые скрытыми файлами или точечными файлами), если только начальный не.
введен буквально.*
или[.]*
или?*
или*.*
илиdir/*
не будут включать точечные файлы..*
илиdir/.*
будет.Так что вы могли бы сделать:
однако некоторые оболочки, в том числе
bash
(но неzsh
,mksh
ниfish
), имеют ту ошибочную характеристику, что расширение.*
включает в себя.
и..
специальные записи каталога, что вам здесь не нужно (и, как правило, никогда не требует включения глобуса, поэтому я и называю это ошибкой).По этой причине вы обнаружите, что иногда люди используют (в оболочках типа Борна):
Это три глобуса, первый из которых соответствует не скрытым файлам, второй - имена файлов, начинающиеся с
.
символа, за которым следует другой символ,.
а третий - имена файлов, начинающиеся с..
символа, за которым следует хотя бы один символ.Однако у некоторых современных оболочек есть лучшие способы обойти это
ЗШ
С помощью
zsh
вы можете использовать(D)
спецификатор glob, чтобы указать, что глобус должен включать точечные файлы:zsh
также исправлено другое несоответствие оболочки Bourne в том, что если шаблон не совпадает,mv
команда не запускается.Как сказано выше, он также никогда не будет включать
.
ни..
в свои глобусы, такбудет в безопасности. Однако, если нет соответствующего файла
*
или нет соответствующего файла,.*
команда будет прервана, поэтому было бы лучше использовать:Как и в некоторых других оболочках, вы также можете заставить все глобусы включать точечные файлы (например, если вы хотите, чтобы точечные файлы включались чаще, чем нет) с помощью:
или же:
После этого, если вы хотите, чтобы определенный глобус не включал точечные файлы, вы можете написать это:
Или же:
удар
К сожалению
bash
, нет глобальных классификаторов. Таким образом, вы можете включить глобальное включение dotfile. Вbash
синтаксис:(и использовать
[^.]*
для шаров без скрытых файлов).С
dotglob
,bash
не включает.
ни..
в глобусы, как*
, но все же делает для глобусов, как.*
.Если вы установите
GLOBIGNORE
переменную в непустое значение, она автоматически включит этуdotglob
опцию и исключит.
и..
из.*
глобусов, но не изdir/.*
или.*/file
из (!), Так что защита практически бесполезна. Вы могли бы сделать,GLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'
но тогда это сломало бы шары как*/.
или./*
или../*
.Лучшее решение - использовать
[.]*
илиdir/[.]*
или[.]*/file
(сdotglob
включенным) для расширения файлов точек, кроме.
и..
.рыбы
fish
шары не включают.
ни..
. Когда нет совпадения, в зависимости от версии, он будет работать какzsh
(илиbash -o failglob
) илиbash -o nullglob
.Будет работать, если есть как скрытые, так и не скрытые файлы. В противном случае, YMMV и с некоторыми версиями, он может вызвать,
mv -- /dest
если нет файла вообще.ksh93
Никаких глобус-классификаторов
ksh93
тоже нет. Вы можете включать дотфайлы в глобусы с помощью:В отличие от
bash
sGLOBIGNORE
, это сделано правильно, а также устраняет проблему.*
включения.
и..
.йаш
yash
имеетdot-glob
параметр (set -o dot-glob
), но в отличиеbash
от глобальных расширений (даже*
) включает,.
и..
поэтому он довольно бесполезен.Tcsh
Работает как в
bash
, то есть*
включает файлы точек, кроме.
и,..
но.*
все еще включает в себя.
и..
(и вы можете использовать[.]*
для расширения скрытых файлов, кроме.
и..
).источник
Самый простой способ в bash для печати соответствующих файлов точек, игнорируя
.
и..
это:Тестировать:
Он печатал все файлы с точками или без, с заметным исключением
.
и..
.Ваш пример также будет работать правильно:
Пусто файлов, которые имеют значение.
Системные файлы
.
..
все еще существуют, но расширение оболочки (используя *) не будет включать их.И Dest каталог ination содержит все файлы:
Почему?
Это работает, потому что настройка GLOBIGNORE имеет следующие побочные эффекты:
shopt -s dotglob
) для файлов математических точек в расширениях..
и..
игнорируются, когда установлен GLOBIGNORE, а не NULL.Подробности в руководстве:
LESS=+'/The GLOBIGNORE' man bash
.Кроме того, нам нужно установить переменную GLOBIGNORE, которая будет содержать имя, которое не может совпадать ни с одним именем файла:
косая черта (и что-то еще в качестве двойной меры предосторожности).
Также может быть полезно установить nullglob, если это необходимо, чтобы избежать получения,
*
когда нет файла, соответствующего*
.источник
Очень интересует эта настройка GLOBIGNORE = / + / @ user79743
Из моего опыта снятия с охраны dotglob это плохой бизнес почти всех команд (ср, мв и т.д.) , но то же самое относится установка на nullglob (особенно с регулярными выражениями , которые затем нужно убегающих!).
Тем не менее, если вам нужно установить их в начале вашей программы, но вмешиваться в определенные части, где вы вызываете такие команды, как cp, mv и т. Д. Или используете регулярные выражения, просто сделайте это:
источник