it-swarm-eu.dev

Kontrola z skriptu Shell, pokud adresář obsahuje soubory

Jak mohu zkontrolovat, zda adresář obsahuje soubory?

Něco podobného

if [ -e /some/dir/* ]; then echo "huzzah"; fi;

ale který funguje, pokud adresář obsahuje jeden nebo několik souborů (výše uvedený seznam funguje pouze s přesně 0 nebo 1 soubory).

95
ionn

Řešení zatím používají ls. Zde je celé bash řešení:

#!/bin/bash
shopt -s nullglob dotglob     # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
61
Bruno De Fraine

Tři nejlepší triky


shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))

Tento trik je 100% bash a vyvolává (shání) sub-Shell. Nápad je z Bruno De Fraine a zlepšil se o komentář { teambob

files=$(shopt -s nullglob dotglob; echo your/dir/*)
if (( ${#files} ))
then
  echo "contains files"
else 
  echo "empty (or does not exist or is a file)"
fi

Poznámka: žádný rozdíl mezi prázdným adresářem a neexistujícím adresářem (a to ani v případě, že je zadaná cesta souborem).

Podobná alternativa a další podrobnosti (a další příklady) jsou k dispozici v 'oficiální' FAQ pro #bash IRC kanál :

if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
then
  echo "contains files"
else 
  echo "empty (or does not exist, or is a file)"
fi

[ -n "$(ls -A your/dir)" ]

Tento trik je inspirován článek nixCraft zaúčtován v roce 2007. Přidat 2>/dev/null potlačit výstupní chybu "No such file or directory".
Viz také odpověď Andrew Taylor (2008) a gr8can8dian 's odpověď (2011).

if [ -n "$(ls -A your/dir 2>/dev/null)" ]
then
  echo "contains files (or is a file)"
else
  echo "empty (or does not exist)"
fi

nebo jednofázová verze bashismu:

[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"

Poznámka:ls vrátí $?=2, když adresář neexistuje. Ale žádný rozdíl mezi souborem a prázdným adresářem.


[ -n "$(find your/dir -Prune -empty)" ]

Tento poslední trik je inspirován gravstarova odpověď kde -maxdepth 0 je nahrazeno -Prune a vylepšeno komentářem { phils .

if [ -n "$(find your/dir -Prune -empty 2>/dev/null)" ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

variace používající -type d:

if [ -n "$(find your/dir -Prune -empty -type d 2>/dev/null)" ]
then
  echo "empty directory"
else
  echo "contains files (or does not exist or is not a directory)"
fi

Vysvětlení: 

  • find -Prune je podobné než find -maxdepth 0 s použitím méně znaků
  • find -empty vytiskne prázdné adresáře a soubory
  • find -type d vytiskne pouze adresáře

Poznámka: Můžete také nahradit [ -n "$(find your/dir -Prune -empty)" ] pouze zkrácenou verzí níže:

if [ `find your/dir -Prune -empty 2>/dev/null` ]
then
  echo "empty (directory or file)"
else
  echo "contains files (or does not exist)"
fi

Tento poslední kód funguje ve většině případů, ale uvědomte si, že škodlivé cesty mohou vyjádřit příkaz ...

114
olibre

Jak na to:

if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi

Tímto způsobem není nutné generovat úplný seznam obsahu adresáře. read je jak zahodit výstup, tak vyjádřit hodnotu jako true, jen když je něco čteno (tj. /some/dir/ je prázdné find).

47
mweerden

Snaž se:

if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
19
Greg Hewgill
# Works on hidden files, directories and regular files
### isEmpty()
# This function takes one parameter:
# $1 is the directory to check
# Echoes "huzzah" if the directory has files
function isEmpty(){
  if [ "$(ls -A $1)" ]; then
    echo "huzzah"
  else 
    echo "has no files"
  fi
}
14
gr8can8dian

Dejte si pozor na adresáře se spoustou souborů! Vyhodnocení příkazu ls by mohlo nějakou dobu trvat.

IMO nejlepším řešením je ten, který používá 

find /some/dir/ -maxdepth 0 -empty
12
Gravstar
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi
9
Andrew Taylor

Mohl byste porovnat výstup tohoto?

 ls -A /some/dir | wc -l
5
DGM
 # Kontroluje, zda adresář obsahuje žádné skryté soubory. 
 # 
 # Usage: if isempty "$ HOME"; pak echo "Vítejte doma"; fi 
 # 
 isempty () {
 pro _ief v $ 1/*; do 
 pokud [-e "$ _ief"]; pak 
 návrat 1 
 fi 
 provedeno 
 návrat 0 
} 

Některé poznámky k provádění:

  • Smyčka for se vyhne volání externího procesu ls. Stále přečte všechny položky adresáře jednou. To lze optimalizovat pouze zapisováním programu C, který používá readdir () explicitně.
  • test -e uvnitř smyčky zachytí případ prázdného adresáře, v tomto případě bude proměnné _ief přiřazena hodnota "somedir/*". Pouze pokud tento soubor existuje, funkce vrátí "nonempty"
  • Tato funkce bude fungovat ve všech implementacích POSIX. Ale uvědomte si, že Solaris/bin/sh nespadá do této kategorie. Jeho implementace test nepodporuje příznak -e.
4
Roland Illig

To mi řekne, zda je adresář prázdný, nebo ne, počet souborů, které obsahuje.

directory="/some/dir"
number_of_files=$(ls -A $directory | wc -l)

if [ "$number_of_files" == "0" ]; then
    echo "directory $directory is empty"
else
    echo "directory $directory contains $number_of_files files"
fi
3
Daishi

To může být opravdu pozdní reakce, ale zde je řešení, které funguje. Tento řádek pouze rozpozná existenci souborů! Nebude vám falešně pozitivní, pokud existují adresáře.

if find /path/to/check/* -maxdepth 0 -type f | read
  then echo "Files Exist"
fi
2
bitstreamer
dir_is_empty() {
   [ "${1##*/}" = "*" ]
}

if dir_is_empty /some/dir/* ; then
   echo "huzzah"
fi

Předpokládejme, že nemáte soubor * do /any/dir/you/check, měl by pracovat s bashdashposhbusybox sh a zsh ale (pro zsh) vyžaduje unsetopt nomatch.

Výkony by měly být srovnatelné s libovolnou ls, která používá * (glob), myslím, že bude pomalé na adresářích s mnoha uzly (moje /usr/bin s 3000+ soubory šel ne tak pomalu), bude používat alespoň dostatek paměti pro přidělení všech dirs/názvy souborů ( a více) jak oni jsou všichni předali (resolved) k funkci jako argumenty, někteří Shell pravděpodobně mají limity na množství argumentů a/nebo délka argumentů.

Přenosný rychlý O(1) nulový zdroj prostředků ke kontrole, zda je adresář prázdný, by bylo hezké mít.

Aktualizace

Výše uvedená verze se nevztahuje na skryté soubory/dirs, v případě, že je vyžadován další test, jako jsou is_empty z triky Rich's sh (POSIX Shell) :

is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0 )

Ale místo toho přemýšlím o něčem takovém:

dir_is_empty() {
    [ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}

Nějaké znepokojení nad koncem lomítka rozdíly od argumentu a najít výstup když dir je prázdný, a koncové nové řádky (ale toto by mělo být snadno ovladatelné), bohužel v mém busyboxsh ukázat co je pravděpodobně chyba na find -> dd potrubí s výstupem\t zkráceno náhodně (pokud jsem použil cat výstup je vždy stejný, zdá se být dd s argumentem count).

1
Alex

ZSH

Vím, že otázka byla označena za bash; ale jen pro orientaci pro zsh users:

Test pro prázdný adresář

Chcete-li zkontrolovat, zda foo není prázdné:

$ for i in foo(NF) ; do ... ; done

kde, jestliže foo je non-prázdný, kód v for bloku bude vykonán.

Test na prázdný adresář

Kontrola, zda je foo prázdná:

$ for i in foo(N/^F) ; do ... ; done

kde, jestliže foo je prázdný, bude proveden kód v bloku for.

Poznámky

Nemuseli jsme citovat výše uvedený adresář foo, ale můžeme to udělat, pokud potřebujeme:

$ for i in 'some directory!'(NF) ; do ... ; done

Můžeme také testovat více než jeden objekt, i když to není adresář:

$ mkdir X     # empty directory
$ touch f     # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done  # echo empty directories
X

Vše, co není adresářem, bude ignorováno.

Doplňky

Vzhledem k tomu, že jsme globbing, můžeme použít jakoukoliv glob (nebo rozšíření ortézy):

$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf                    # create regular file
$ touch X1/f                  # directory X1 is not empty
$ touch Y1/.f                 # directory Y1 is not empty
$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo  # print empty directories
X X2 Y Y2

Můžeme také zkoumat objekty, které jsou umístěny v poli. S výše uvedenými adresáři například:

$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*)                     # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z

Můžeme tedy testovat objekty, které již mohou být nastaveny v parametru pole.

Všimněte si, že kód v bloku for je samozřejmě prováděn na každém adresáři. Pokud to není žádoucí, můžete jednoduše zaplnit parametr pole a pak pracovat s tímto parametrem:

$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories

Vysvětlení

Pro uživatele zsh existuje kvalifikátor (F) glob (viz man zshexpn), který odpovídá "full" (non-empty) adresářům:

$ mkdir X Y
$ touch Y/.f        # Y is now not empty
$ touch f           # create a regular file
$ ls -dF *          # list everything in the current directory
f X/ Y/
$ ls -dF *(F)       # will list only "full" directories
Y/

Kvalifikátor (F) uvádí objekty, které odpovídají: je adresář A není prázdný. Takže (^F) odpovídá: není adresář OR prázdný. Samotné (^F) by také například uvádělo pravidelné soubory. Jak je tedy vysvětleno na stránce zshexp man, potřebujeme také kvalifikátor (/) glob, který uvádí pouze adresáře:

$ mkdir X Y Z
$ touch X/f Y/.f    # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z

Chcete-li zkontrolovat, zda je daný adresář prázdný, můžete tedy spustit:

$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished

a jen proto, aby se ujistil, že se nepřebere prázdný adresář:

$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished

Jejda! Protože Y není prázdný, zsh nenajde žádné shody pro (/^F) ("adresáře, které jsou prázdné"), a tak vypíše chybovou zprávu, že nebyly nalezeny žádné shody pro glob. Proto musíme potlačit tyto možné chybové zprávy pomocí kvalifikátoru (N) glob:

$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished

Pro neprázdné adresáře tedy potřebujeme kvalifikátor (N/^F), který můžete číst jako: „nevarujte mě o poruchách, adresářích, které nejsou plné“.

Stejně tak pro prázdné adresáře potřebujeme kvalifikátor (NF), který můžeme také přečíst jako: „nevarujte mě o selháních, úplných adresářích“.

1
Zorawar

Malá variace Brunovy odpovědi :

files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ] 
then
    echo "Contains files"
else
    echo "Empty"
fi

Funguje to pro mě

1
loockass
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
0
Toby

Jsem překvapen wooledge guide na prázdných adresářích nebyl zmíněn. Tento průvodce a všechny wooledge je opravdu nutné číst pro otázky typu Shell.

Poznámka z této stránky:

Nikdy se nepokoušejte analyzovat výstup ls. Dokonce i řešení ls -A mohou přerušit (např. Na HP-UX, pokud jste root, ls -A dělá Přesný opak toho, co dělá, když nejste root - a ne, nemůžu doplnit něco, co neuvěřitelně hloupě).

Ve skutečnosti se člověk může chtít vyhnout přímé otázce úplně. Obvykle se lidé chtějí dozvědět, zda je adresář Prázdný, protože chtějí dělat něco, co v něm obsahuje soubory atd. Podívejte se na větší otázku . Vhodným řešením může být například jeden z těchto příkladů:

   # Bourne
   find "$somedir" -type f -exec echo Found unexpected file {} \;
   find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \;  # GNU/BSD
   find "$somedir" -type d -empty -exec cp /my/configfile {} \;   # GNU/BSD

Nejčastěji je vše, co je opravdu potřeba, něco takového:

   # Bourne
   for f in ./*.mpg; do
        test -f "$f" || continue
        mympgviewer "$f"
    done

Jinými slovy, osoba, která žádá o otázku, si mohla myslet, že explicitní test prázdného adresáře byl Potřebný, aby se vyhnul chybovému hlášení, jako je mympgviewer: ./*.mpg: Žádný takový soubor nebo adresář, když ve skutečnosti ne takový test je vyžadován.

0
bishop

Já bych šel na find:

if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
    echo "$dir has NO files"
else
    echo "$dir has files"

To zkontroluje výstup hledání pouze souborů v adresáři, aniž by procházel podadresáři. Poté zkontroluje výstup pomocí volby -z převzaté z man test:

   -z STRING
          the length of STRING is zero

Podívejte se na některé výsledky:

$ mkdir aaa
$ dir="aaa"

Prázdný adresář:

$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

Jenom v tom:

$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty

Soubor v adresáři:

$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile 

Soubor v podadresáři:

$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
0
fedorqui

S nějakým řešením bych mohl najít jednoduchý způsob, jak zjistit, zda jsou v adresáři soubory. To může rozšířit s více příkazy grep zkontrolovat konkrétně .xml nebo .txt soubory atd. Ex: ls /some/dir | grep xml | wc -l | grep -w "0"

#!/bin/bash
if ([ $(ls /some/dir | wc -l  | grep -w "0") ])
    then
        echo 'No files'
    else
        echo 'Found files'
fi
0
chanaka777

Zatím jsem neviděl odpověď, která používá grep, což by podle mého názoru dalo jednodušší odpověď (ne příliš mnoho zvláštních symbolů!). Zde je návod, jak bych Zkontroloval, zda v adresáři existují nějaké soubory pomocí bourne Shell:

vrátí počet souborů v adresáři:

ls -l <directory> | egrep -c "^-"

můžete vyplnit cestu k adresáři, do kterého je zapsán adresář. První polovina potrubí zajišťuje, že první znak výstupu je "-" pro každý soubor. egrep pak spočítá počet řádků, které začínají symbolem pomocí regulárních výrazů. vše, co musíte udělat, je uložit číslo, které získáte, a porovnat jej pomocí backquotes jako: 

 #!/bin/sh 
 fileNum=`ls -l <directory> | egrep -c "^-"`  
 if [ $fileNum == x ] 
 then  
 #do what you want to do
 fi

x je proměnná podle vašeho výběru.

0
Jecht Tyre

Zadejte adresář hardcoded nebo jako argument Poté inicializujte hledání prohledávání všech souborů uvnitř adresáře. Zkontrolujte, zda je návrat nálezu null. .] Ozvěte data nálezu

#!/bin/bash

_DIR="/home/user/test/"
#_DIR=$1
_FIND=$(find $_DIR -type f )
if [ -n "$_FIND" ]
then
   echo -e "$_DIR contains files or subdirs with files \n\n "
   echo "$_FIND"
else
echo "empty (or does not exist)"
fi
0
GiannakopoulosJ

Jednoduchá odpověď s bash :

if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
0
Thomas Steinbach

Míchám Prune věci a poslední odpovědi, jsem se dostal

find "$some_dir" -Prune -empty -type d | read && echo empty || echo "not empty"

, který funguje i pro cesty s mezerami

0
Laurent G