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

Scripting Bash: test per cartelle vuote

Voglio testare se una directory non contiene alcun file. Se è così, salterò alcune elaborazioni.

Ho provato quanto segue:

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

Che dà il seguente errore:

line 1: [: too many arguments

C'è una soluzione/alternativa?

Risposte (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

Inoltre, sarebbe bello controllare se la directory esiste prima.

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

Non c'è bisogno di contare nulla o di globi di shell. Potete anche usare read in combinazione con find. Se l'output di find è vuoto, restituirà false:

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

Questo dovrebbe essere portatile.

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

Con FIND(1) (sotto Linux e FreeBSD) potete guardare in modo non ricorsivo una voce di directory tramite “-maxdepth 0” e verificare se è vuota con “-empty”. Applicato alla domanda questo dà:

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

Un modo hacky, ma solo bash, senza PID:

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

Questo sfrutta il fatto che la builtin test esce con 2 se le viene dato più di un argomento dopo -e: Per prima cosa, "$1"/* glob viene espanso da bash. Questo risulta in un argomento per file. Quindi

  • Se non ci sono file, l'asterisco in test -e "$1"* non si espande, quindi Shell ricade nel tentativo di file chiamato *, che restituisce 1.

  • …eccetto se c'è effettivamente un file chiamato esattamente *, allora l'asterisco si espande in beh, asterisco, che finisce con la stessa chiamata di cui sopra, cioè test -e "dir/*", solo che questa volta restituisce 0. (Grazie @TrueY per averlo fatto notare. )

  • Se c'è un solo file, viene eseguito test -e "dir/file", che restituisce 0.

  • Ma se ci sono più file di 1, viene eseguito test -e "dir/file1" "dir/file2", che bash riporta come errore di utilizzo, cioè 2.

case avvolge l'intera logica in modo che solo il primo caso, con 1 stato di uscita sia riportato come successo.

Possibili problemi che non ho controllato:

  • Ci sono più file rispetto al numero di argomenti consentiti - immagino che questo potrebbe comportarsi in modo simile al caso con 2+ file.

  • O c'è effettivamente un file con un nome vuoto - non sono sicuro che sia possibile su qualsiasi OS/FS sano di mente.

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

Questo farà il lavoro nella directory di lavoro corrente (.):

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

o lo stesso comando diviso su tre righe solo per essere più leggibile:

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

Basta sostituire ls -1A . | wc -l con ls -1A <target-directory> | wc -l se avete bisogno di eseguirlo su una cartella di destinazione diversa.

Modifica : Ho sostituito -1a con -1A (vedi commento di @Daniel)

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

Usate quanto segue:

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

In questo modo, sei indipendente dal formato di output di ls. -mindepth salta la directory stessa, -maxdepth evita di difendere ricorsivamente le sottodirectory per accelerare le cose.

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

Usando un array:

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

Che ne dite di testare se la directory esiste e non è vuota in una dichiarazione 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

Penso che la soluzione migliore sia:

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

grazie a https://stackoverflow.com/a/91558/520567

Questo è un edit anonimo della mia risposta che potrebbe essere utile o meno a qualcuno: Una leggera modifica dà il numero di file:

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

Questo funzionerà correttamente anche se i nomi dei file contengono spazi.

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

La domanda era:

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

La risposta è:

if ls -1qA . | grep -q .
    then ! exit 1
    else : # Dir is empty
fi
1
1
1
2018-05-25 17:06:53 +0000
if find "${DIR}" -prune ! -empty -exit 1; then
    echo Empty
else
    echo Not Empty
fi

EDIT: Penso che questa soluzione funzioni bene con gnu find, dopo una rapida occhiata alla implementazione . Ma questo potrebbe non funzionare, per esempio, con netbsd’s find . Infatti, quello usa il campo st\size di stat(2). Il manuale lo descrive come:

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.

Una soluzione migliore, anche più semplice, è:

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

Inoltre, il -prune nella prima soluzione è inutile.

EDIT: niente -exit per gnu find… la soluzione di cui sopra va bene per il find di NetBSD. Per GNU find, questo dovrebbe funzionare:

if [-z "`find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit`"]; then
    echo Empty
else
    echo Not Empty
fi
0
0
0
2020-01-15 17:46:01 +0000

Ho fatto questo approccio:

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

Questo funziona per me, per controllare ed elaborare i file nella directory ../IN, considerando che lo script è nella directory ../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

Questa è tutta roba fantastica - l'ho appena trasformata in uno script in modo da poter controllare le directory vuote sotto quella corrente. Il sotto dovrebbe essere messo in un file chiamato ‘findempty’, messo nel percorso da qualche parte in modo che bash possa trovarlo e poi chmod 755 per eseguirlo. Può essere facilmente modificato per le vostre esigenze specifiche, credo.

#!/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

Per qualsiasi directory diversa da quella corrente, potete controllare se è vuota provando a rmdir, perché rmdir è garantito che fallisca per le directory non vuote. Se rmdir ha successo, e si vuole effettivamente che la directory vuota sopravviva al test, basta mkdir di nuovo.

Non usate questo trucco se ci sono altri processi che potrebbero essere scombussolati da una directory di cui sono a conoscenza che cessa brevemente di esistere.

Se rmdir non funziona per voi, e potreste testare directory che potrebbero potenzialmente contenere un gran numero di file, qualsiasi soluzione che si basi su shell globbing potrebbe diventare lenta e/o incorrere in limiti di lunghezza della linea di comando. Probabilmente è meglio usare find in questo caso. La soluzione più veloce per find che mi viene in mente è

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

Questo funziona per le versioni GNU e BSD di find ma non per quella Solaris, che manca di tutti quegli operatori find. Amo il tuo lavoro, Oracle.

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

Potete provare a rimuovere la directory e aspettare un errore; rmdir non cancellerà la directory se non è vuota.

_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