Bash kabuk betiğinde bir dizinin var olup olmadığını kontrol etmek için hangi komut kullanılabilir?
Bash kabuk betiğinde bir dizinin var olup olmadığını kontrol etmek için hangi komut kullanılabilir?
Yanıtlar:
Kabuk betiğinde bir dizinin olup olmadığını kontrol etmek için aşağıdakileri kullanabilirsiniz:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Veya bir dizinin bulunup bulunmadığını kontrol etmek için:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
Bununla birlikte, Jon Ericson'un işaret ettiği gibi, bir dizine sembolik bir bağın da bu denetimi geçeceğini dikkate almazsanız, sonraki komutlar amaçlandığı gibi çalışmayabilir. Örneğin, bunu çalıştırırken:
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
Hata mesajı üretir:
rmdir: failed to remove `symlink': Not a directory
Bu nedenle, sonraki komutlar dizinleri beklerse, sembolik bağlantılara farklı davranılması gerekebilir:
if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
# It is a symlink!
# Symbolic link specific commands go here.
rm "$LINK_OR_DIR"
else
# It's a directory!
# Directory command goes here.
rmdir "$LINK_OR_DIR"
fi
fi
Değişkenleri sarmak için kullanılan çift tırnak işaretlerini özellikle dikkate alın. Bunun nedeni başka bir cevapta 8jean tarafından açıklanmıştır .
Değişkenler boşluk veya başka sıradışı karakterler içeriyorsa, büyük olasılıkla komut dosyasının başarısız olmasına neden olur.
[ ! -d "$DIRECTORY" ]
değilse de doğru olacaktır . Gibi bir şey düşünün ; bu bir dosya ise başarısız olur . (Tabii ki yine de başarılı olup olmadığını kontrol etmelisiniz ; başarısız olmasının birkaç nedeni vardır.)$DIRECTORY
if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
"$DIRECTORY"
mkdir
-d
) hem de symlink ( -L
) için test yapmak yerine , değişkene bir eğik çizgi eklemek daha kolaydır if [ -d "${THING:+$THING/}" ]
. Bir dizin ekstra eğik çizgiyi önemsemez. Bir dosya yanlış olarak değerlendirilir. Boş boş kalır, bu yüzden yanlıştır. Ve bir sembolik bağlantı hedefi çözülecektir. Tabii ki, hedefinize bağlıdır. Oraya gitmek istiyorsanız , bu iyi. Eğer isterseniz silin , sonra bu cevap kod iyidir.
Değişkenleri bir Bash betiğinde referans alırken her zaman çift tırnak içine almayı unutmayın. Bu günlerde çocuklar dizin adlarında boşluklar ve diğer komik karakterler olabileceği fikriyle büyüyorlar. (Uzaylar! Günlerimde, süslü alanımız yoktu!;))
Bir gün, bu çocuklardan biri senaryonuzu $DIRECTORY
set ile çalıştırır ve senaryonuz "My M0viez"
patlar. Bunu istemiyorsun. Öyleyse bunu kullan.
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
-D testinin bazı şaşırtıcı sonuçlar üretebileceğini unutmayın :
$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory
Aşağıdaki dosya: "Bir dizin ne zaman bir dizin değildir?" Cevap: "Bir dizin için bir sembolik bağlantı olduğunda." Biraz daha kapsamlı bir test:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
Bash koşullu ifadeleri ile Bash kılavuzunda daha fazla bilgi ve [
yerleşik komut ve [[
bileşik iletişimde daha fazla bilgi bulabilirsiniz .
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... veya bir komut için bu bağlantıları ve dirs hem çalışır:rm -r tmpdir
Mantık testleri yazmayı daha doğal hale getiren çift parantezli versiyonunu buluyorum test
:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
if [[ -d "$TARFILE" ]]
alıyorum [[: bulunamadı
[[ ]]
desteklenir, ancak aslında farklı bir işlevsellik sağlamaz [ ]
. Taşınabilirlik bir endişe kaynağıysa, [ ]
gerekli geçici çözümleri uygulayın.
Daha kısa form:
[ -d "$DIR" ] && echo "Yes"
if $dir is a dir, then echo "yes"
? Açıklama biraz yardımcı olur :)
cmd && other
ortak bir stenondur if cmd; then other; fi
- bu Boole mantığını destekleyen çoğu programlama dili ile çalışır ve kısa devre değerlendirmesi olarak bilinir .
set -e
(bu bir kabuk programlama en iyi uygulamasıdır ).
[ -d "$DIR" ]
kontrol edilir (ardından gelir && echo Yes
), bu yüzden set -e
komut dosyası davranışında hiçbir fark yaratmadığına inanıyorum (yani test başarısız olursa, komut dosyası normal şekilde devam eder).
Bir dizinin var olup olmadığını kontrol etmek için aşağıdaki if
gibi basit bir yapı kullanabilirsiniz :
if [ -d directory/path to a directory ] ; then
# Things to do
else #if needed #also: elif [new condition]
# Things to do
fi
Negatif olarak da yapabilirsiniz:
if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory
Not : Dikkatli olun. Açma ve kapama ayraçlarının her iki tarafında boş alanlar bırakın.
Aynı sözdizimi ile şunları kullanabilirsiniz:
-e: any kind of archive
-f: file
-h: symbolic link
-r: readable file
-w: writable file
-x: executable file
-s: file size greater than zero
Bir dizinin veya dosyanın mevcut olup olmadığını test etmek için basit bir komut dosyası:
if [ -d /home/ram/dir ] # For file "if [-f /home/rama/file]"
then
echo "dir present"
else
echo "dir not present"
fi
Dizinin mevcut olup olmadığını kontrol etmek için basit bir komut dosyası:
mkdir tempdir # If you want to check file use touch instead of mkdir
ret=$?
if [ "$ret" == "0" ]
then
echo "dir present"
else
echo "dir not present"
fi
Yukarıdaki komut dosyaları dizinin mevcut olup olmadığını kontrol eder
$?
son komut başarılı olursa "0", başka bir değer sıfır dışında bir değer döndürür. Varsayalım tempdir
zaten var. Sonra mkdir tempdir
aşağıdaki gibi bir hata verecektir:
mkdir: 'tempdir' dizini oluşturulamıyor: Dosya var
Kullanabilirsiniz test -d
(bkz. man test
).
-d file
Dosya varsa ve bir dizinse doğrudur.
Örneğin:
test -d "/etc" && echo Exists || echo Does not exist
Not: test
Komut koşullu ifade ile aynıdır [
(bkz. man [
), Bu nedenle kabuk komut dosyalarında taşınabilir.
[
- Bu,test
yerleşik ile eşanlamlıdır , ancak son argümanın]
açılışa uyması için bir gerçek olması gerekir[
.
Olası seçenekler veya daha fazla yardım için şunları kontrol edin:
help [
help test
man test
veya man [
Veya tamamen işe yaramaz bir şey için:
[ -d . ] || echo "No"
İşte çok pragmatik bir deyim:
(cd $dir) || return # Is this a directory,
# and do we have access?
Genellikle bir işlevde sarın:
can_use_as_dir() {
(cd ${1:?pathname expected}) || return
}
Veya:
assert_dir_access() {
(cd ${1:?pathname expected}) || exit
}
Bu yaklaşımla ilgili güzel bir şey, iyi bir hata mesajı düşünmem gerekmemesidir.
cd
zaten standart hataya standart bir satır mesajı verecek . Ayrıca, sunabileceğimden daha fazla bilgi verecektir. cd
Alt kabuğun içinde gerçekleştirildiğinde, ( ... )
komut arayanın geçerli dizinini etkilemez. Dizin varsa, bu alt kabuk ve işlev yalnızca bir işlemdir.
Sonraki argüman cd
:: ${1:?pathname expected}
. Bu, aşağıda daha ayrıntılı olarak açıklanan daha ayrıntılı bir parametre ikame şeklidir.
Tl; dr: Bu işleve iletilen dize boşsa, yine alt kabuktan çıkar ( ... )
ve verilen hata iletisiyle işlevden döneriz .
ksh93
Man sayfasından alıntı :
${parameter:?word}
parameter
Ayarlanmışsa ve null değilse , değerini değiştirin; aksi takdirde, yazdırınword
ve kabuktan çıkın (etkileşimli değilse). Eğerword
göz ardı edilir, standart bir mesaj basılır.
ve
:
İki nokta üst üste yukarıdaki ifadelerden çıkarılırsa, kabuk yalnızca parametrenin ayarlanıp ayarlanmadığını kontrol eder.
Buradaki ifade word
, boşluk da dahil olmak üzere herhangi bir makul dizeye atıfta bulunduğu gibi kabuk belgelerine özgüdür .
Bu özel durumda, standart hata mesajının 1: parameter not set
yeterli olmadığını biliyorum , bu yüzden burada beklediğimiz değer türüne - pathname
bir dizinin yakınlaştırmasına biliyorum .
Felsefi bir not:
Kabuk, nesne yönelimli bir dil değildir, bu nedenle mesaj diyor pathname
, değil directory
. Bu seviyede, basit olmayı tercih ederim - bir işleve ilişkin argümanlar sadece dizelerdir.
test -d
@ Grundlefleck açıkladığı gibidir.
test -d /unreadable/exists
argüman mevcut olsa bile başarısız olur.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
Yukarıdaki kod dizinin var olup olmadığını ve yazılabilir olup olmadığını kontrol eder.
DIRECTORY=/tmp
if [ -d "$DIRECTORY" ]; then
echo "Exists"
fi
space
sonra hatırla [
-> [`` -d . eksik alan nedeniyle hata aldım
Bash istemine bu kodu yazın:
if [ -d "$DIRECTORY" ]; then
# If true this block of code will execute
fi
find
Alt dizinler içinde klasörün varlığını kontrol edin:
found=`find -type d -name "myDirectory"`
if [ -n "$found"]
then
# The variable 'found' contains the full path where "myDirectory" is.
# It may contain several lines if there are several folders named "myDirectory".
fi
Geçerli dizindeki bir desene göre bir veya birkaç klasörün varlığını kontrol edin:
found=`find -maxdepth 1 -type d -name "my*"`
if [ -n "$found"]
then
# The variable 'found' contains the full path where folders "my*" have been found.
fi
Her iki kombinasyon. Aşağıdaki örnekte, geçerli dizinde klasörün varlığını kontrol eder:
found=`find -maxdepth 1 -type d -name "myDirectory"`
if [ -n "$found"]
then
# The variable 'found' is not empty => "myDirectory"` exists.
fi
find -maxdepth 1 -type d -name 'pattern'
. Bu numaraya cevabınızı eklersem sakıncası var mı? Şerefe;)
Aslında, kurşun geçirmez bir yaklaşım elde etmek için birkaç araç kullanmalısınız:
DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # Now you're testing
echo "It's a dir";
fi
Kullandığınız sürece boşluklar ve özel karakterler hakkında endişelenmenize gerek yoktur "${}"
.
Bunun [[]]
kadar taşınabilir olmadığını unutmayın []
, ancak çoğu insan Bash'in modern sürümleriyle çalıştığından (sonuçta, çoğu insan komut satırı :-p ile bile çalışmaz), fayda sorundan daha büyüktür.
Atlamadan if
önce bakmak yerine yapmak istediğiniz her şeyi yapmayı düşündünüz mü ?
Yani, girmeden önce bir dizinin varlığını kontrol etmek istiyorsanız, sadece bunu yapmayı deneyin:
if pushd /path/you/want/to/enter; then
# Commands you want to run in this directory
popd
fi
Eğer verdiğiniz yol pushd
varsa, girersiniz ve bu 0
yolla çıkar , yani then
ifadenin bir kısmı yürütülür. Eğer yoksa, hiçbir şey olmayacaktır (dizinin mevcut olmadığını söyleyen bazı çıktılar dışında, muhtemelen hata ayıklama için yararlı bir yan etkidir).
Kendinizi tekrar etmenizi gerektiren bundan daha iyi görünüyor:
if [ -d /path/you/want/to/enter ]; then
pushd /path/you/want/to/enter
# Commands you want to run in this directory
popd
fi
Aynı şey ile çalışır cd
, mv
, rm
var olmayan dosyalar üzerinde bunları çalışırsanız, onlar bir hatayla çıkmak ve onu yok belirten bir mesaj yazdırmak ve edeceğiz ... vb then
blok atlanır. Bunları varolan dosyalar üzerinde denerseniz, komut yürütülür ve durumuyla başlar ve bloğunuzun yürütülmesine 0
izin verir then
.
Birden fazla dizini kontrol etmek için bu kodu kullanın:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
Dizinin var olup olmadığını kontrol edin, yoksa bir tane yapın:
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
mkdir -p "$DIRECTORY"
Aynı etki için kullanabilirsiniz .
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
Not: Değişkenlerden alıntı yapmak iyi bir uygulamadır.
Açıklama:
-d
: bir dizin olup olmadığını kontrol edin-L
: sembolik bir bağlantı olup olmadığını kontrol edin[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Bu cevap bir kabuk betiği olarak tamamlandı
$ is_dir ~
YES
$ is_dir /tmp
YES
$ is_dir ~/bin
YES
$ mkdir '/tmp/test me'
$ is_dir '/tmp/test me'
YES
$ is_dir /asdf/asdf
NO
# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
echo "Folder doesnt exist: $DIR";
exit;
fi
function show_help()
{
IT=$(CAT <<EOF
usage: DIR
output: YES or NO, depending on whether or not the directory exists.
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
DIR=$1
if [ -d $DIR ]; then
echo "YES";
exit;
fi
echo "NO";
Kullanımı -e
çek dosyaları denetlemek ve bu dizinleri içerir edecektir.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
Gereğince Jonathan Yorumu:
Dizini oluşturmak istiyorsanız ve henüz mevcut değilse, o zaman en basit teknik mkdir -p
dizini ve yoldaki eksik dizinleri - kullanmaktır ve dizin zaten varsa başarısız olmaz, böylece hepsini yapabilirsiniz bir kerede:
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
Bu tamamen doğru değil ...
Bu dizine gitmek istiyorsanız, dizinde yürütme haklarına da sahip olmanız gerekir. Belki de yazma haklarına sahip olmanız gerekir.
Bu nedenle:
if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
# ... to go to that directory (even if DIRECTORY is a link)
cd $DIRECTORY
pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
# ... to go to that directory and write something there (even if DIRECTORY is a link)
cd $DIRECTORY
touch foobar
fi
file
Programı kullanın . Tüm dizinlerin de Linux'ta dosyalar olduğu düşünüldüğünde, aşağıdaki komutu vermek yeterli olacaktır:
file $directory_name
Var olmayan bir dosyayı kontrol etme: file blah
Çıktı: cannot open 'blah' (No such file or directory)
Mevcut bir dizini kontrol etme: file bluh
Çıktı: bluh: directory
ls
İle birlikte komut -l
(uzun listeleme) seçeneği dönüşleri dosyaları ve dizinleri hakkında bilgi bağlıyor.
Özellikle ls -l
çıktının ilk karakteri genellikle a d
veya a -
(tire) olur. Bir durumunda d
listelenen biri kesin bir dizindir.
Yalnızca bir satırdaki aşağıdaki komut, verilen ISDIR
değişkenin bir dizine yol içerip içermediğini size bildirir :
[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
Pratik kullanım:
[claudio@nowhere ~]$ ISDIR="$HOME/Music"
[claudio@nowhere ~]$ ls -ld "$ISDIR"
drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
YES, /home/claudio/Music is a directory.
[claudio@nowhere ~]$ touch "empty file.txt"
[claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt"
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directoy"
Sorry, /home/claudio/empty file.txt is not a directory
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
Bir dizinin var olup olmadığını kontrol etmek istiyorsanız, gerçek bir dizin veya bir sembolik bağlantıdan bağımsız olarak şunu kullanın:
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
Açıklama: "ls" komutu, dizin veya sistem bağlantısı yoksa "ls: / x: Böyle bir dosya veya dizin yok" hatası verir ve "$?" Aracılığıyla alabileceğiniz dönüş kodunu non -boş (normalde "1"). "Ls" çağırdıktan sonra doğrudan dönüş kodunu kontrol ettiğinizden emin olun.
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
(1)
[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"
(2)
[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"
(3)
[[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists"
Yukarıda sunulan yaklaşımlardan biriyle ilgili bir sorun bulunursa:
İle ls
komuta; bir dizinin mevcut olmadığı durumlar - bir hata mesajı gösterilir
[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists
-ksh: not: not [Böyle bir dosya veya dizin yok]
Orada harika çözümler var, ancak doğru dizinde değilseniz her komut dosyası başarısız olur. Yani şöyle kodlayın:
if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
# It is a symlink!
# Symbolic link specific commands go here
rm "$LINK_OR_DIR"
else
# It's a directory!
# Directory command goes here
rmdir "$LINK_OR_DIR"
fi
fi
ancak yürütme sırasında kontrol ettiğiniz alt dizine sahip bir dizindeyseniz başarılı bir şekilde yürütülür.
Bunun gibi ilk soruyu anlıyorum: Kullanıcının dosya sistemindeki konumundan bağımsız olarak bir dizin olup olmadığını doğrulamak için. Yani 'find' komutunu kullanmak hile yapabilir:
dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d
Bu çözüm iyidir çünkü dosyaları / dizinleri ararken yararlı bir özellik olan joker karakterlerin kullanımına izin verir. Tek sorun, aranan dizin yoksa, 'find' komutunun standart çıktıya hiçbir şey basmayacak (zevkime uygun zarif bir çözüm değil) ve yine de sıfır çıkışa sahip olmasıdır. Belki birisi bu konuda düzelebilir.
locate
ancak başka bir şey için hoş olmayabilir ...
--
şiddetle tavsiye edilir (seçenek sonu işaretçisi). Aksi takdirde, değişkeniniz seçenek gibi görünen bir şey içeriyorsa, komut dosyası boşluklarda olduğu gibi başarısız olur.