Как проверить результат расширения имени файла в bash? - PullRequest
3 голосов
/ 21 августа 2009

Я хочу проверить, есть ли в каталоге файлы в bash. Мой код здесь.

for d in {,/usr/local}/etc/bash_completion.d ~/.bash/completion.d
     do              
         [ -d "$d" ] && [ -n "${d}/*" ] &&                         

         for f in $d/*; do                                                                                                           
             [ -f "$f" ] && echo "$f" && . "$f"                        

         done                                                                                                                        
     done

Проблема в том, что у файла ~ / .bash / extension.d нет файла. Таким образом, $ d / * рассматривается как простая строка "~ / .bash / extension.d / *", а не пустая строка, которая является результатом расширения имени файла. В результате этого кода bash пытается запустить

. "~/.bash/completion.d/*" 

и, конечно, генерирует сообщение об ошибке.

Кто-нибудь может мне помочь?

Ответы [ 5 ]

6 голосов
/ 21 августа 2009

Если вы установите опцию nullglob bash, через

shopt -s nullglob

тогда при отбрасывании удаляются шаблоны, которые не соответствуют ни одному файлу.

4 голосов
/ 29 июля 2010
# NOTE: using only bash builtins
# Assuming $d contains directory path

shopt -s nullglob

# Assign matching files to array
files=( "$d"/* )

if [ ${#files[@]} -eq 0 ]; then
    echo 'No files found.'
else
    # Whatever
fi

Присвоение массиву имеет и другие преимущества, включая желаемую (правильную!) Обработку имен файлов / путей, содержащих пробелы, и простую итерацию без использования вложенной оболочки, как показано в следующем коде:

find "$d" -type f |
while read; do
    # Process $REPLY
done

Вместо этого вы можете использовать:

for file in "${files[@]}"; do
    # Process $file
done

с тем преимуществом, что цикл запускается основной оболочкой, а это означает, что побочные эффекты (например, присвоение переменных), сделанные в цикле, видны для оставшейся части сценария. Конечно, это также способ быстрее, если производительность является проблемой.
Наконец, массив также может быть вставлен в аргументы командной строки (без разделения аргументов, содержащих пробелы):

$ md5sum fileA "${files[@]}" fileZ

Вы всегда должны пытаться правильно обрабатывать файлы / пути, содержащие пробелы, потому что однажды они произойдут!

0 голосов
/ 25 февраля 2010

Другой подход

# prelim stuff to set up d
files=`/bin/ls $d`
if [ ${#files} -eq 0 ]
then
    echo "No files were found"
else
    # do processing
fi
0 голосов
/ 24 ноября 2009
find() {
 for files in "$1"/*;do
    if [ -d "$files" ];then
        numfile=$(ls $files|wc -l)
        if [ "$numfile" -eq 0 ];then
            echo "dir: $files has no files"
            continue
        fi
        recurse "$files"
    elif [ -f "$files" ];then
         echo "file: $files";
        :
    fi
 done
}
find /path
0 голосов
/ 24 августа 2009

Вы можете использовать find напрямую следующим образом:

for f in $(find {,/usr/local}/etc/bash_completion.d ~/.bash/completion.d -maxdepth 1 -type f);
do echo $f; . $f;
done

Но find напечатает предупреждение, если какая-то часть каталога не найдена, вы можете либо поставить 2> /dev/null, либо вызвать find после тестирования, если каталоги существуют (как в вашем коде).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...