Как использовать шаблон. * В bash, но исключить родительский каталог (..)?
Часто бывает, что я хочу выполнить команду для всех файлов (включая скрытые файлы) в каталоге. Когда я пытаюсь использовать
chmod g+w * .*
он изменяет разрешения для всех файлов, которые я хочу (в каталоге), и всех файлов в родительском каталоге (который я хочу оставить в покое).
Есть ли подстановочный знак, который делает правильную вещь или мне нужно начать использовать find?
Ответы
Ответ 1
Вам понадобятся два шаблона glob для покрытия всех возможных "точечных файлов": .[^.]*
и ..?*
.
Первое совпадение со всеми элементами каталога с двумя или более символами, где первый символ является точкой, а второй символ не является точкой. Второе записывает записи с тремя или более символами, начинающимися с ..
(это исключает ..
, потому что оно имеет только два символа и начинается с .
, но включает (маловероятные) записи, такие как ..foo
).
chmod g+w .[^.]* ..?*
Это должно хорошо работать в большинстве оболочек и подходит для скриптов.
Для регулярного интерактивного использования шаблоны могут быть слишком сложными для запоминания. В этих случаях у вашей оболочки может быть более удобный способ пропустить .
и ..
.
zsh всегда исключает .
и ..
из таких шаблонов, как .*
.
С помощью bash вы должны использовать переменную оболочки GLOBIGNORE.
# bash
GLOBIGNORE=.:..
echo .*
Возможно, вы захотите установить GLOBIGNORE в одном из ваших файлов настройки bash (например, .bash_profile
/.bash_login
или .bashrc
).
Остерегайтесь, однако, привыкнуть к этой настройке, если вы часто используете другие среды.
Если вы запускаете команду типа chmod g+w .*
в среде, где отсутствует ваша настройка, вы неожиданно закончите, включая .
и ..
в своей команде.
Кроме того, вы можете настроить оболочки для включения "точечных файлов" в шаблоны, которые не начинаются с явной точки (например, *
).
# zsh
setopt glob_dots
# bash
shopt -s dotglob
# show all files, even "dot files"
echo *
Ответ 2
Обычно я просто использовал бы . .[a-zA-Z0-9]*
, так как мои имена файлов, как правило, следуют определенным правилам, но это не поймает все возможные случаи.
Вы можете использовать:
chmod g+w $(ls -1a | grep -v '^..$')
который будет в основном перечислять все файлы и каталоги, вычеркивать родительский каталог, а затем обрабатывать остальные. Остерегайтесь пробелов в именах файлов, но они будут обрабатывать их как отдельные файлы.
Конечно, если вы просто хотите делать файлы, вы можете использовать:
find . -maxdepth 0 -type f -exec chmod g+w {} ';'
или еще одно решение, которое должно делать все файлы и каталоги, кроме ..
one:
for i in * .* ; do if [[ ${i} != ".." ]] ; then chmod g+w "$i"; fi done
но теперь вы попадаете на территорию, где могут потребоваться сценарии или псевдонимы.
Ответ 3
То, что я сделал, было
tar --directory my_directory --file my_directory.tar --create `ls -A mydirectory/`
Работает отлично, ls -A my_directory
расширяется до всего в каталоге, кроме .
и ..
. Нет wierd globs и на одной строке.
ps: Возможно, кто-то скажет мне, почему это не очень хорошая идея.: Р
Ответ 4
Как насчет:
shopt -s dotglob
chmod g+w ./*
Ответ 5
Поскольку вы не хотите устанавливать dotglob для остальной части вашего сеанса bash, вы можете установить его для одного набора команд, выполнив в этом подпроцессе:
$ (shopt -s dotglob; chmod g+w ./*)
Ответ 6
Если вы уверены, что имена скрытых файлов с двумя символами никогда не будут использоваться, то проще всего выполнить:
chmod g+w * ...*