2011-01-12 24 views
73

Próbuję napisać bardzo prosty skrypt w Ubuntu, który pozwoliłby mi przekazać go albo nazwę pliku, albo katalog, i być w stanie zrobić coś konkretnego, gdy jest to plik i coś jeszcze, gdy jest to katalog. Problemem, który mam, jest to, że nazwa katalogu (lub prawdopodobnie także pliki) zawiera spacje lub inne znaki, które można wypisać.Sprawdź, czy przekazany argument jest plikiem lub katalogiem w BASH

Oto mój podstawowy kod poniżej i kilka testów.

#!/bin/bash 

PASSED=$1 

if [ -d "${PASSED}" ] ; then 
    echo "$PASSED is a directory"; 
else 
    if [ -f "${PASSED}" ]; then 
     echo "${PASSED} is a file"; 
    else 
     echo "${PASSED} is not valid"; 
     exit 1 
    fi 
fi 

A oto wyjście:

[email protected]~ $ ./scripts/testmove.sh /home/andy/ 
/home/andy/ is a directory 

[email protected]~ $ ./scripts/testmove.sh /home/andy/blah.txt 
/home/andy/blah.txt is a file 

[email protected]~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt 
/home/andy/blah with a space.txt is not valid 

[email protected]~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/ 
/home/andy with a space/ is not valid 

Wszystkie te ścieżki są ważne, a istnieje.

+4

'if'-'else' konstrukty w bash również wspierać' elif'. Po prostu dla FYI. –

+0

powinien mieć tutaj cytaty: 'PASSED =" $ 1 "' –

+3

@glenn - Co ciekawe, cytaty nie są wymagane w zmiennych zadaniach. –

Odpowiedz

102

To powinno zadziałać. Nie jestem pewien, dlaczego to się nie udaje. Poprawnie cytujesz swoje zmienne. Co się stanie, jeśli użyjesz tego skryptu z podwójnym [[]]?

if [[ -d $PASSED ]]; then 
    echo "$PASSED is a directory" 
elif [[ -f $PASSED ]]; then 
    echo "$PASSED is a file" 
else 
    echo "$PASSED is not valid" 
    exit 1 
fi 

Podwójne nawiasy kwadratowe jest rozszerzeniem bash do [ ]. Nie wymaga podawania cytowanych zmiennych, nawet jeśli zawierają spacje.

Warto również przetestować: -e, aby sprawdzić, czy ścieżka istnieje bez sprawdzania, jaki to plik.

7

Przynajmniej napisać kod bez krzaczaste drzewa:

#!/bin/bash 

PASSED=$1 

if [ -d "${PASSED}" ] 
then echo "${PASSED} is a directory"; 
elif [ -f "${PASSED}" ] 
then echo "${PASSED} is a file"; 
else echo "${PASSED} is not valid"; 
    exit 1 
fi 

Kiedy kładę, że do pliku „xx.sh” i utworzyć plik „XX sh” i uruchom go, otrzymuję:

$ cp /dev/null "xx sh" 
$ for file in . xx*; do sh "$file"; done 
. is a directory 
xx sh is a file 
xx.sh is a file 
$ 

Biorąc pod uwagę, że masz problemy, być może należy debugować skrypt dodając linię:

ls -l "${PASSED}" 

To pokaże to, co ls myśli o nazwach, które przekazują skrypt.

-1

ZAKTUALIZOWANO: Zostałem cofnięty, więc postanowiłem ponownie napisać odpowiedź, dziękuję za informację zwrotną.

Za pomocą polecenia „plik” może być przydatna dla:

#!/bin/bash 
check_file(){ 

if [ -z "${1}" ] ;then 
echo "Please input something" 
return; 
fi 

f="${1}" 
result="$(file $f)" 
if [[ $result == *"cannot open"* ]] ;then 
     echo "NO FILE FOUND ($result) "; 
elif [[ $result == *"directory"* ]] ;then 
     echo "DIRECTORY FOUND ($result) "; 
else 
     echo "FILE FOUND ($result) "; 
fi 

} 

check_file ${1} 

przykłady wyjściowe:

$ ./f.bash login 
DIRECTORY FOUND (login: directory) 
$ ./f.bash ldasdas 
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or directory)) 
$ ./f.bash evil.php 
FILE FOUND (evil.php: PHP script, ASCII text) 

FYI: Odpowiedzi Powyższe pracy, ale można użyć -s do pomocy w sytuacjach dziwnych sprawdzając pierwszego ważnego pliku:

#!/bin/bash 

check_file(){ 
    local file="${1}" 
    [[ -s "${file}" ]] || { echo "is not valid"; return; } 
    [[ -d "${file}" ]] && { echo "is a directory"; return; } 
    [[ -f "${file}" ]] && { echo "is a file"; return; } 
} 

check_file ${1} 
-2
#!/bin/bash                        
echo "Please Enter a file name :"                   
read filename                        
if test -f $filename                      
then                          
     echo "this is a file"                    
else                          
     echo "this is not a file"                   
fi 
2

Korzystanie -f i -d przełączników na /bin/test:

F_NAME="${1}" 

if test -f "${F_NAME}" 
then         
    echo "${F_NAME} is a file" 
elif test -d "${F_NAME}" 
then 
    echo "${F_NAME} is a directory" 
else         
    echo "${F_NAME} is not valid" 
fi 
Powiązane problemy