Geçilen bağımsız değişkenin Bash'ta dosya veya dizin olup olmadığını kontrol edin


156

Ben bir dosya adı veya bir dizin ya da bir dosya olduğunda belirli bir şey ve bir dizin olduğunda başka bir şey yapmak için izin verecek Ubuntu son derece basit bir komut dosyası yazmaya çalışıyorum. Yaşadığım sorun, dizin adı veya büyük olasılıkla dosyalar da adında boşluklar veya diğer kaçan karakterler olduğunda.

Aşağıda temel kodum ve birkaç test var.

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

Ve işte çıktı:

andy@server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory

andy@server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file

andy@server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid

andy@server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid

Bu yolların tümü geçerli ve var.


5
if- elseBash'teki yapılar da desteklenir elif. Sadece FYI.

3
@glenn - Merakla, değişken atamalarda tırnak işaretleri gerekmez.
John Kugelman

Kabuk betiğinde bir dizinin olup olmadığını denetlemenin olası kopyası .
jww

Yanıtlar:


211

Bu işe yaramalı. Neden başarısız olduğundan emin değilim. Değişkenlerinizi doğru şekilde söylüyorsunuz. Bu komut dosyasını double ile kullanırsanız ne olur [[ ]]?

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

Çift köşeli parantez bash uzantısıdır [ ]. Boşluk olsalar bile değişkenlerin alıntılanmasını gerektirmez.

Ayrıca denemeye değer: -ene tür bir dosya olduğunu test etmeden bir yolun var olup olmadığını test etmek.


9

En azından kodu gür ağaç olmadan yazın:

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

Ben bir "xx.sh" bir dosyaya koymak ve "xx sh" bir dosya oluşturmak ve çalıştırmak, ben olsun:

$ 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
$

Sorun yaşadığınız göz önüne alındığında, komut dosyası hata ayıklama ekleyerek şunları yapmalısınız:

ls -l "${PASSED}"

Bu lssize senaryoyu geçtiğiniz isimler hakkında ne düşündüğünü gösterecektir .


4

"Dosya" komutunu kullanmak bunun için yararlı olabilir:

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

Çıktı örnekleri:

$ ./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) 

Bilginize: yukarıdaki cevaplar işe yarıyor, ancak önce geçerli bir dosyayı kontrol ederek garip durumlarda yardımcı olmak için -s komutunu kullanabilirsiniz:

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

Yani, boş dosyalar geçerli değil ( -sboş olmayan bir dosya olup olmadığını , biri sıfır olmayan bir boyutu kontrol eder)? Ve özel bir blok, karakter özel, FIFO, vb. Symlinks muhtemelen bağlantının en ucundakilere karar verir; kırık semboller daha sorunludur.
Jonathan Leffler

Bir düzenleme olarak ne öneriyorsunuz, yorumunuzu takip etmiyorum
Mike Q

--briefBayrağını kullanın file. Sadece directoryolduğu zaman çıktı verir.
Berkant Ipek

2

Kullanma -fve -daçma /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

Genel olarak, zaten eşdeğer cevaplar olduğunda eski bir soruya yeni bir cevap eklemek için uğraşmamalısınız. Eklenecek şaşırtıcı yeni bilgileriniz varsa, ancak her şey bir cevap verirse. Ama söylediklerin zaten söylendi. ( testnormalde yerleşik bir kabuktur, ancak genellikle /bin/testve gibi bir yürütülebilir dosya da vardır /bin/[.)
Jonathan Leffler

1

Daha zarif bir çözüm

echo "Enter the file name"
read x
if [ -f $x ]
then
    echo "This is a regular file"
else
    echo "This is a directory"
fi

2
Komut satırı bağımsız değişkenleri kullanmak yerine girdiler sormak genellikle "daha zarif" değildir. Sen testinde değişkeni alıntı olmalıdır: if [ -f "$x" ].
Jonathan Leffler

1
function check_file_path(){
    [ -f "$1" ] && return
    [ -d "$1" ] && return
    return 1
}
check_file_path $path_or_file

-1

Bu çalışmalı:

#!/bin/bash

echo "Enter your Path:"
read a

if [[ -d $a ]]; then 
    echo "$a is a Dir" 
elif [[ -f $a ]]; then 
    echo "$a is the File" 
else 
    echo "Invalid path" 
fi

2
Lütfen, bir soruyu cevaplarken bazı açıklamalar ekleyebilir misiniz?
Sébastien Temprado

-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 

Sorudaki kodun yaptığı gibi çıktıdaki dosya adını yankılamak en iyisidir. Dosya adı sormanın bir iyileştirme olduğu açık değildir. Kod, dosyalar, dizinler ve 'diğer' arasında ayrım yapmaz. Yanıt yoksa veya verilecek yeni bilgileriniz varsa eski bir soruya yeni bir yanıt eklemek sorun değildir. Burada durum böyle değil.
Jonathan Leffler

-2

Bir astar

touch bob; test -d bob && echo 'dir' || (test -f bob && echo 'file')

sonuç true (0) (dir) veya true (0) (dosya) veya false (1) (ikisi de)


Ben değiştirirseniz touch bobile mkdir bob, ben çıktı alın: dirve fileiki satırda.
Jonathan Leffler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.