2011-10-31 03:47:31 +0000 2011-10-31 03:47:31 +0000
106
106

Бэш-скриптинг: тест на пустую директорию

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

я попробовал следующее:

if [./* == "./*"]; then
    echo "No new file"
    exit 1
fi

Это дает следующую ошибку:

line 1: [: too many arguments

Есть ли решение/альтернатива?

Ответы (18)

135
135
135
2011-10-31 03:53:28 +0000
if [-z "$(ls -A /path/to/dir)"]; then
   echo "Empty"
else
   echo "Not Empty"
fi

Кроме того, было бы здорово проверить, существует ли эта директория раньше.

24
24
24
2013-10-29 21:07:29 +0000

Не нужно ничего считать, или глобусы скорлупы. Вы также можете использовать read в комбинации с find. Если выход find пуст, вы вернете false:

if find /some/dir -mindepth 1 | read; then
   echo "dir not empty"
else
   echo "dir empty"
fi

Это должно быть портативным.

20
20
20
2011-10-31 10:53:57 +0000
if [-n "$(find "$DIR_TO_CHECK" -maxdepth 0 -type d -empty 2>/dev/null)"]; then
    echo "Empty directory"
else
    echo "Not empty or NOT a directory"
fi
14
14
14
2011-11-01 14:51:09 +0000
#!/bin/bash
if [-d /path/to/dir]; then
    # the directory exists
    ["$(ls -A /path/to/dir)"] && echo "Not Empty" || echo "Empty"
else
    # You could check here if /path/to/dir is a file with [-f /path/to/dir]
fi
4
4
4
2018-09-26 13:50:40 +0000

С помощью FIND(1) (под Linux и FreeBSD) вы можете невозвратно посмотреть на запись в каталоге через “-maxdepth 0” и проверить, пустая ли она с помощью “-empty”. Применительно к вопросу, который это дает:

if test -n "$(find ./ -maxdepth 0 -empty)" ; then
    echo "No new file"
    exit 1
fi
4
4
4
2014-10-24 01:23:28 +0000

Хакки, но только бэш, без PID:

is_empty() {
    test -e "$1/"* 2>/dev/null
    case $? in
        1) return 0 ;;
        *) return 1 ;;
    esac
}

Это использует тот факт, что test builtin выходит с 2, если задать более одного аргумента после -e: Во-первых, "$1"/* глобус расширяется на bash. В результате получаем по одному аргументу в каждом файле. Итак,

  • если файлов нет, звездочка в test -e "$1"* не расширяется, поэтому Shell возвращается к пробному файлу с именем *, который возвращает 1.

  • …за исключением того, что если на самом деле есть один файл с именем точно *, то звездочка расширяется до нуля, что заканчивается тем же вызовом, что и выше, т.е. test -e "dir/*", только на этот раз возвращается 0. (Спасибо @TrueY за указание на это. )

  • Если есть один файл, то запускается test -e "dir/file", который возвращает 0.

  • Но если файлов больше 1, то запускается test -e "dir/file1" "dir/file2"is, который bash сообщает об ошибке использования, т.е. 2.

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

Возможные проблемы, которые я не проверял:

  • Файлов больше, чем допустимых аргументов - думаю, это может вести себя так же, как и в случае с 2+ файлами.

  • Или на самом деле есть файл с пустым именем - я не уверен, что это возможно на любой нормальной операционной системе/FS.

4
4
4
2011-10-31 10:06:28 +0000

Это сделает работу в текущей рабочей директории (.):

[`ls -1A . | wc -l` -eq 0] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."

или та же самая команда, разделенная на три строки, чтобы быть более читабельной:

[`ls -1A . | wc -l` -eq 0] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."

Просто замените ls -1A . | wc -l на ls -1A <target-directory> | wc -l, если вам нужно запустить его в другой целевой папке.

Правка : Я заменил -1a на -1A (см. комментарий Дэниела).

3
3
3
2011-10-31 10:17:15 +0000

Используйте следующее:

count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [$count -eq 0] ; then
   echo "No new file"
   exit 1
fi

Таким образом, вы не зависите от выходного формата ls. -mindepth пропускает сам каталог, -maxdepth предотвращает рекурсивную защиту в подкаталогах для ускорения.

3
3
3
2014-08-12 21:46:08 +0000

Используя массив:

files=( * .* )
if (( ${#files[@]} == 2 )); then
    # contents of files array is (. ..)
    echo dir is empty
fi
2
2
2
2018-06-20 09:17:01 +0000

Как насчет тестирования, если каталог существует и не пустой в одном операторе if оператор

if [[-d path/to/dir && -n "$(ls -A path/to/dir)"]]; then 
  echo "directory exists"
else
  echo "directory doesn't exist"
fi
1
1
1
2013-10-29 20:57:27 +0000

Я думаю, что лучшим решением будет:

files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[["$files"]] || echo "dir empty"

благодаря https://stackoverflow.com/a/91558/520567

Это анонимное редактирование моего ответа, которое может кому-то пригодиться, а может и не пригодиться: Небольшое изменение дает количество файлов:

files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]}) 
echo "MYPATH contains $files files"

Это будет работать правильно, даже если имена файлов содержат пробелы.

1
1
1
2020-02-16 18:53:46 +0000

Вопрос был:

if [./* == "./*"]; then
    echo "No new file"
    exit 1
fi

Ответ был:

if ls -1qA . | grep -q .
    then ! exit 1
    else : # Dir is empty
fi
1
1
1
2018-05-25 17:06:53 +0000

0x1 и 0x2 и 0x2 и EDIT: Я думаю, что это решение прекрасно работает с gnu найти, после quick посмотрите на [ внедрение ]0x3 &. Но это может не сработать, например, с netbsd’s find . Действительно, для этого используется поле st_size stat(2). В руководстве это описано как:

if find "${DIR}" -prune ! -empty -exit 1; then
    echo Empty
else
    echo Not Empty
fi

Лучшее решение, также более простое:

st_size The size of the file in bytes. The meaning of the size
                   reported for a directory is file system dependent.
                   Some file systems (e.g. FFS) return the total size used
                   for the directory metadata, possibly including free
                   slots; others (notably ZFS) return the number of
                   entries in the directory. Some may also return other
                   things or always report zero.

Кроме того, -prune в 1-м решении бесполезно.

EDIT: нет -выхода для gnu find… вышеприведенное решение хорошо для поиска NetBSD. Для GNU find это должно сработать:

if find "${DIR}" -mindepth 1 -exit 1; then
    echo Empty
else
    echo Not Empty
fi
0
0
0
2020-01-15 17:46:01 +0000

Я сделал этот подход:

CHECKEMPTYFOLDER=$(test -z "$(ls -A /path/to/dir)"; echo $?)
if [$CHECKEMPTYFOLDER -eq 0]
then
  echo "Empty"
elif [$CHECKEMPTYFOLDER -eq 1]
then
  echo "Not Empty"
else
  echo "Error"
fi
0
0
0
2018-05-02 13:29:51 +0000

Это работает для меня, чтобы проверить и обработать файлы в каталоге ../IN, учитывая, что скрипт находится в каталоге ../Script:

FileTotalCount=0

    for file in ../IN/*; do
    FileTotalCount=`expr $FileTotalCount + 1`
done

if test "$file" = "../IN/*"
then

    echo "EXITING: NO files available for processing in ../IN directory. "
    exit

else

  echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."

# Rest of the Code
0
0
0
2012-02-24 10:06:37 +0000

Это все отличный материал - просто сделал его в скрипт, так что я могу проверить на пустые директории ниже текущего. Ниже следует поместить в файл под названием ‘findempty’, поместить в путь где-нибудь так, чтобы bash мог его найти, а затем chmod 755 для запуска. Может быть легко изменен в соответствии с вашими конкретными потребностями, я думаю.

#!/bin/bash
if ["$#" == "0"]; then 
find . -maxdepth 1 -type d -exec findempty "{}" \;
exit
fi

COUNT=`ls -1A "$*" | wc -l`
if ["$COUNT" == "0"]; then 
echo "$* : $COUNT"
fi
-1
-1
-1
2018-01-10 17:12:56 +0000

Для любой директории, отличной от текущей, вы можете проверить, пустая ли она, попробовав rmdir it, потому что rmdir гарантированно даст сбой для непустых директорий. Если rmdir пройдет успешно, и вы действительно хотите, чтобы пустая директория пережила тест, просто mkdir снова.

Не используйте этот хак, если есть другие процессы, которые могут быть дискомбинированы каталогом, о котором они знают, и которые ненадолго прекращают свое существование.

Если rmdir не будет работать на вас, и вы, возможно, тестируете каталоги, которые потенциально могут содержать большое количество файлов, любое решение, полагающееся на оболочку-глобулятор, может замедлиться и/или попасть в пределы длины командной строки. Вероятно, лучше использовать find в этом случае. Самое быстрое решение find, которое я могу придумать, идет как

is_empty() {
    test -z $(find "$1" -mindepth 1 -printf X -quit)
}

Это работает для GNU и BSD версий find, но не для Solaris, в котором отсутствует каждый из этих операторов find. Любите свою работу, Oracle.

-3
-3
-3
2018-04-08 20:54:13 +0000

Можно попытаться удалить каталог и дождаться ошибки; rmdir не удалит каталог, если он не пустой.

_path="some/path"
if rmdir $_path >/dev/null 2>&1; then
   mkdir $_path # create it again
   echo "Empty"
else
   echo "Not empty or doesn't exist"
fi