Bash: как проверить, существует ли каталог и есть ли в нем файлы - PullRequest
0 голосов
/ 12 мая 2019

Я хочу распечатать все имена подкаталогов с именами файлов содержимого под именем каталога. Если подкаталог пуст, не печатайте имя каталога и не переходите к следующему подкаталогу. Применимая часть моего кода:

for dirs in "$mydir"/*
do
   if [ -d "$dirs" -type f" ] && [ "find "$dirs" -type f" ]
   then
      echo "Processing directory $dirs"
         for subfiles in $dirs/*
         do
            echo "Encoding $subfiles"
         done
   fi
done

Если я пропущу второе условие первого оператора if, тогда пустые каталоги выведут свое имя на экран, и под ним будет указан * (я думаю, это означает, что в каталоге ничего нет). Часть после && не вызывает никаких ошибок, но она не мешает пустым каталогам видеть остальную часть этого раздела кода.

Как мне заставить это работать?

Ответы [ 4 ]

0 голосов
/ 13 мая 2019

Включение nullglob может упростить вещи:

shopt -s nullglob
if [ some/dir/* ]; then
    echo directory exists and is not empty
fi

Когда установлен nullglob, выражения glob, которые ничего не соответствуют, возвращают пустую строку.

0 голосов
/ 12 мая 2019

Вместо того, чтобы просматривать все и проверять, является ли каждый файл или непустой каталог, почему бы просто не искать файлы и непустые каталоги в первую очередь?

На основании вашего заявления, что I want to print out all sub-directory names with their content file names below the directory name. это будет просто:

find . -mindepth 2 -maxdepth 2 ! -path . -type f -print0 |
    awk -v RS='\0' -F'/' '!seen[$(NF-1)]++{print "dir", $(NF-1)} {print "file", $NF}'

Например:

$ find . -printf '%y %p\n'
d .
f ./file
d ./tmp1
d ./tmp2
f ./tmp2/bar
f ./tmp2/foo

$ find . -mindepth 2 -maxdepth 2 ! -path . -type f -print0 |
    awk -v RS='\0' -F'/' '!seen[$(NF-1)]++{print "Processing directory", $(NF-1)} {print "Encoding", $NF}'
Processing directory tmp2
Encoding bar
Encoding foo

Массаж для костюма. Если вам НЕОБХОДИМО выполнить команду оболочки для каждого файла, тогда нет необходимости задействовать awk, и вы можете просто изменить вышеупомянутое значение на:

$ cat ../tst.sh
#!/bin/env bash
declare -A seen
while read -r -d '' line; do
    path="${line%/*}"
    dir="${path#*/}"
    file="${line##*/}"
    (( ! $(( seen[dir]++ )) )) && printf 'Processing directory %s\n' "$dir"
    printf 'Encoding %s\n' "$file"
done < <(find . -mindepth 2 -maxdepth 2 ! -path . -type f -print0)

$ ../tst.sh
Processing directory tmp2
Encoding bar
Encoding foo
0 голосов
/ 12 мая 2019

Решение в чистом виде:

is_empty_dir() { [[ "*..." = "$(printf %s * .*)" ]]; }

Он должен безопасно обрабатывать имена файлов, начинающиеся с . или -.

. Имеет нулевой статус выхода, если текущий каталог пуст,ненулевое значение в противном случае.


Пример использования:

is_empty_dir() { [[ "*..." = "$(printf %s * .*)" ]]; }

if [[ -d /tmp ]]
then
    cd /tmp
    if is_empty_dir
    then
        echo "/tmp is empty"
    else
        echo "/tmp is NOT empty"
    fi
else
    echo "/tmp does not exist"
fi
0 голосов
/ 12 мая 2019

Измените ваше условие, чтобы проверить пустые каталоги:

for dirs in "$mydir"/*
do
   if [ -d "$dirs" ] && [ -n "$(ls -A $dirs)" ]
   then
      echo "Processing directory $dirs"
         for subfiles in $dirs/*
         do
            echo "Encoding $subfiles"
         done
   fi
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...