Обычно история команд сохраняется к скрытому файлу в корневом каталоге пользователя. Кроме этого, можно зарегистрироваться к stderr или системному журналу.
Поскольку Вы уже заметили, что удар не будет соответствовать a .
в начале имени или наклонной черты. Для изменения соответствия относительно точки, необходимо установить dotglob
опция - удар человека:
dotglob If set, bash includes filenames beginning with a `.' in the results of pathname expansion.
Позволять/устанавливать его с использованием удара shopt
, например:
shopt -s dotglob
Для zsh можно также использовать dotglob
опция, но но необходимо будет использовать setopt
включить его, например:
setopt dotglob
Я протестировал это, и это решает проблему:
shopt -s dotglob
Вывод:
~/stackexchangeanswers/40662$ ls -hal dest
total 8.0K
drwxr-xr-x 2 jodiec jodiec 4.0K 2012-06-12 22:15 .
drwxr-xr-x 4 jodiec jodiec 4.0K 2012-06-12 22:15 ..
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 1
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 .1
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 2
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 .2
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 3
-rw-r--r-- 1 jodiec jodiec 0 2012-06-12 22:15 .3
...snipped....
Самый простой способ в bash печатать файлы с совпадающими точками, игнорируя .
и ..
is:
$ GLOBIGNORE=/+/
$ printf '%s\n' *
Чтобы проверить:
$ cd tmp; mkdir empty; cd empty; touch {,.}{a..h}
$ GLOBIGNORE=/+/
$ ls *
a .a b .b c .c d .d e .e f .f g .g h .h
Он напечатал все файлы с точками или без них, за заметным исключением .
и ..
.
Ваш пример также будет работать правильно:
$ cd /tmp; mkdir {t,d}est; touch test/{,.}{a..h}
$ mv test/* dest/
$ ls -a test
. ..
$ ls -a test/*
ls: cannot access test/*: No such file or directory
Пусто от важных файлов.
Системные файлы .
..
все еще существуют, но расширение оболочки (с использованием *) не будет включать их.
И каталог dest ination содержит все файлы:
$ cd dest
$ ls -a *
a .a b .b c .c d .d e .e f .f g .g h .h
Это работает, потому что установка GLOBIGNORE имеет следующие эффекты стороны :
shopt -s dotglob
) к файлам математических точек в расширениях. .
и ..
игнорируются, если GLOBIGNORE установлен, а не null. Подробности в руководстве: LESS = + '/ The GLOBIGNORE' man bash
.
Кроме того, нам нужно установить переменную GLOBIGNORE, чтобы она содержала имя, с которым не может совпадать ни одно имя файла:
косую черту (и что-то еще в качестве двойной меры предосторожности).
$ GLOBIGNORE=/+/
Также может быть полезно установить nullglob, если это необходимо, чтобы избежать получения *
, когда нет файла, соответствующего *
.
*
- это глобус, который расширяется оболочкой. По умолчанию shell не включает файлы, имя которых начинается с .
(называемые скрытыми файлами или dotfiles), если только ведущее .
вводится буквально.
*
или [.]*
или ?*
или *.*
или dir/*
не будет включать dotfiles.
.*
или dir/.*
будут.
Так что вы могли бы сделать:
mv -- * .* /dest/
однако некоторые оболочки, включая bash
(но не zsh
, mksh
или fish
) имеют ту ошибку, что расширение .*
включает .
и .
специальные записи каталога, которые здесь не нужны (и вообще никогда не нужны, чтобы glob включал их, поэтому я и называю это ошибкой).
По этой причине иногда люди используют (в Bourne-подобных оболочках):
mv -- * .[!.]* ..?* /dest/
Это три глобы, первая из которых соответствует не скрытым файлам, вторая - именам файлов, начинающимся с .
, за которым следует символ, отличный от .
и третий - имена файлов, начинающиеся с ...
, за которым следует хотя бы один символ.
Однако некоторые современные оболочки имеют лучшие способы обойти это
С zsh
вы можете использовать (D)
квалификатор glob, чтобы указать, что glob должен включать dotfiles:
mv -- *(D) /dest/
zsh
также исправил другую ошибку оболочки Bourne, которая заключается в том, что если шаблон не совпадает, команда mv
не выполняется.
Как было сказано выше, она также никогда не будет включать .
или ...
в свои глобусы, поэтому
mv -- * .* /dest/
будет в безопасности. Однако если нет файла, соответствующего *
или файла, соответствующего . *
команда будет прервана, поэтому лучше использовать:
mv -- (*|.*) /dest/
Как и в некоторых других оболочках, вы также можете заставить все глобы включать точечные файлы (например, если вы обнаружите, что хотите, чтобы точечные файлы включались чаще, чем нет) с помощью:
setopt dotglob
or:
set -o dotglob
После этого, если вы хотите, чтобы конкретный glob not включал dotfiles, вы можете написать:
echo *(^D)
Or:
echo [^.]*
К сожалению, bash
не имеет квалификаторов glob. Поэтому вам остается включить включение dotfile глобально. В bash
синтаксис следующий:
shopt -s dotglob
(и используйте [^.]*
для глобов без скрытых файлов).
С dotglob
, bash
не включает .
ни ...
в глобусах типа *
, но все же включает глобусы типа .*
.
Если установить переменную GLOBIGNORE
в непустое значение, то автоматически включается опция dotglob
и исключается .
и ...
из .*
глобов, но не из dir/.*
или .*/file
(!), так что эта мера предосторожности довольно бесполезна. Вы можете сделать GLOBIGNORE='*/.:*/...:./*:.../*:*/./*:*/.../*'
, но тогда это нарушит глобы типа */.
или ./*
или ../*
.
Лучшее решение - использовать [.]*
или dir/[.]*
или [.]*/file
(с включенным dotglob
) для расширения dotfiles, кроме .
и ...
.
fish
глобы не включают .
ни ...
. Когда нет совпадений, в зависимости от версии, это будет работать как zsh
(или bash -o failglob
) или bash -o nullglob
.
mv -- * .* /dest/
Будет работать, если есть как скрытые, так и не скрытые файлы. В противном случае, YMMV и в некоторых версиях может вызвать mv -- /dest
, если файла вообще нет.
В ksh93
также нет квалификатора glob. Вы можете включать dotfiles в globs с помощью:
FIGNORE='@(.|..)'
Вопреки bash
в GLOBIGNORE
, это делается правильно и также устраняет проблему .*
, включающую .
и .
.
yash
имеет опцию dot-glob
(set -o dot-glob
), но, в отличие от bash
, расширения glob (даже из *
) включают .
и .
, так что это довольно бесполезно.
set globdot
Работает как в bash
, то есть *
включает точечные файлы, кроме .
и ...
, но *
по-прежнему включает .
и .
(и вы можете использовать [.]*
для расширения скрытых файлов, кроме .
и .
).
Очень заинтересовал этот параметр GLOBIGNORE = / + / @ user79743
По моему опыту отключение dotglob - это плохой бизнес почти для всех ваших команд (cp, mv и т. Д.), НО то же самое верно , устанавливая nullglob (особенно с регулярными выражениями, которые затем нужно экранировать!).
Тем не менее, если вам все же нужно установить их в начале программы, но мешает работе определенных частей, где вы вызываете такие команды, как cp, mv и т. Д., Или используете регулярные выражения, просто сделайте следующее:
# set dotglob, unset nullglob AFTER this
is_nullglob=$( shopt -s | egrep -i '.*nullglob' )
is_dotglob=$( shopt -s | egrep -i '.*dotglob' )
[[ $is_nullglob ]] && shopt -u nullglob
[[ ! $is_dotglob ]] && shopt -s dotglob
# ... call commands ...
# .....................
# reset dotglob, nullglob to their previous values
[[ $is_nullglob ]] && shopt -s nullglob
[[ ! $is_dotglob ]] && shopt -u dotglob
zsh
, более оптимальный вариант состоит в том, чтобы включить dotglob на основе на шарик:mv test/*(D) /dest
– Stéphane Chazelas 27.04.2016, 14:28