Можно циклично выполниться через все каталоги включая скрытые каталоги (начинающийся с точки) в одной строке и нескольких командах с:
for file in */ .*/ ; do echo "$file is a directory"; done
Если Вы хотите исключить символьные ссылки:
for file in *; do
if [[ -d "$file" && ! -L "$file" ]]; then
echo "$file is a directory";
fi;
done
примечание: использование списка */ .*/
работы в ударе, но также и дисплеи папки .
и ..
в то время как в zsh это не покажет их, но бросит ошибку, если не будет никакого скрытого файла в папке
Более чистая версия, которая будет включать скрытые каталоги и исключать../, будет с dotglob опцией:
shopt -s dotglob
for file in */ ; do echo "$file is a directory"; done
(или setopt dotglob
в zsh)
можно сбросить dotglob с
shopt -u dotglob
Вот версия, которая была упрощена и, что более важно, исправлено цитирование (двойные кавычки вокруг переменных, одинарные кавычки вокруг непеременного текста, где требуется)
#!/bin/bash
logfilepattern='*drupal*.gz php*.gz error*.gz'
function getlogcounts {
echo in getlogcounts
echo "$1"
echo "$2"
ssh "$1" "cd $2 ; ls -l $logfilepattern"
}
getlogcounts me@remoteserver.com /var/log/mylogs
Вы выполняете сценарий на удаленной машине. Этот сценарий содержит $2
и $logfilepattern
(текст между одинарными кавычками передается буквально как аргумент команды ssh
, так что это фрагмент кода для выполнения на другой стороне). Они относятся к переменным оболочки, запущенной на стороне удаления.
На самом деле, вы запускаете две оболочки на удаленной стороне, но это не очень полезно. SSH всегда вызывает оболочку; вы можете передать ей несколько аргументов, но они просто соединяются с пробелами между ними. Оболочка на удаленной стороне выполняет
bash -c \ #script string starts here
cd $2
…
Первая строка вызывает bash
с двумя аргументами: -c
и один пробел. Это вызывает оболочку, которая ничего не делает. Остальная часть удаленной команды выполняется в оболочке, вызванной SSH.
Простой способ сделать то, что вы пытаетесь сделать, следующий
ssh "$1" "cd $2 && ls -l $logfilepattern"
Примечания:
ls
бессмыслен: for file in `ls *`
- это сложный способ написать for file in *
, за исключением того, что разбор вывода ls
ломается, если имена файлов содержат специальные символы. $2
, и $logfilepattern
анализируются как часть сценария, выполняемого на удаленной стороне. Если они содержат что-то вроде $(touch foo)
, то этот фрагмент кода будет выполнен. В данном конкретном случае это не обязательно является проблемой, но вы должны знать об этом. &&
после cd
гарантирует, что команда ssh
немедленно вернется со статусом отказа, если команда cd
не выполнится. Если вы хотите передать содержимое без изменений в удаленную оболочку по SSH, использование только командной строки проблематично, поскольку все, что вы передаете, расширяется на удаленной стороне. Один трюк, который часто работает (но не всегда, это зависит от конфигурации SSH как на клиенте, так и на сервере) - использовать переменные, имя которых начинается с LC_
; предполагается, что это информация о локали, и часто она передается.
LC_DIRECTORY=$2 LC_LOGFILEPATTERN=$logfilepattern ssh "$1" 'cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN'
Обратите внимание на кавычки:
cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN
. Он заключается в одинарные кавычки, чтобы передать этот буквальный текст в качестве аргумента команде ssh
. $LC_DIRECTORY
заключается в двойные кавычки в сценарии, который выполняется на удаленной стороне, чтобы команда cd
была вызвана на содержимом переменной. LC_LOGFILEPATTERN
не заключен в двойные кавычки, потому что это список шаблонов, разделенных пробелами, а именно так трактуется расширение переменной без кавычек. Если вы не можете передавать переменные, вам придется добавить уровень цитирования для защиты переменных, значение которых содержит специальные символы.
q_directory=$(printf %sa "$2" | sed s/\'/\'\\\'\'/g)
q_directory="'${directory%a}'"
q_logfilepattern=$(printf %sa "$logfilepattern" | sed s/\'/\'\\\'\'/g)
q_logfilepattern="'${q_logfilepattern%a}'"
ssh "$1" "logfilepattern=$q_logfilepattern; cd $q_logfilepattern && ls \$logfilepattern"