Perintah apa yang dapat digunakan untuk memeriksa apakah ada direktori atau tidak, dalam skrip Bash shell?
Perintah apa yang dapat digunakan untuk memeriksa apakah ada direktori atau tidak, dalam skrip Bash shell?
Jawaban:
Untuk memeriksa apakah direktori ada dalam skrip shell, Anda dapat menggunakan yang berikut:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Atau untuk memeriksa apakah direktori tidak ada:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
Namun, seperti yang ditunjukkan oleh Jon Ericson , perintah selanjutnya mungkin tidak berfungsi sebagaimana dimaksud jika Anda tidak memperhitungkan bahwa tautan simbolis ke direktori juga akan melewati pemeriksaan ini. Misalnya menjalankan ini:
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
Akan menghasilkan pesan kesalahan:
rmdir: failed to remove `symlink': Not a directory
Jadi tautan simbolik mungkin harus diperlakukan secara berbeda, jika perintah selanjutnya mengharapkan direktori:
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
Perhatikan tanda kutip ganda yang digunakan untuk membungkus variabel. Alasan untuk ini dijelaskan oleh 8jean di jawaban lain .
Jika variabel berisi spasi atau karakter tidak biasa lainnya, mungkin akan menyebabkan skrip gagal.
[ ! -d "$DIRECTORY" ]
akan benar jika $DIRECTORY
tidak ada, atau jika memang ada tetapi bukan direktori. Pertimbangkan sesuatu seperti if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi
; ini akan gagal jika "$DIRECTORY"
merupakan file. (Tentu saja Anda harus memeriksa apakah mkdir
berhasil juga; ada sejumlah alasan mengapa hal itu dapat gagal.)
-d
) dan symlink ( -L
), lebih mudah hanya menambahkan garis miring ke variabel, seperti if [ -d "${THING:+$THING/}" ]
. Direktori tidak akan keberatan dengan slash tambahan. File akan dinilai false. Kosong akan tetap kosong, jadi salah. Dan symlink akan diselesaikan ke tujuannya. Tentu saja, itu tergantung pada tujuan Anda. Jika Anda ingin pergi ke sana, ini tidak masalah. Jika Anda ingin menghapusnya , maka kode dalam jawaban ini lebih baik.
Ingatlah untuk selalu membungkus variabel dalam tanda kutip ganda ketika merujuk mereka dalam skrip Bash. Anak-anak dewasa ini tumbuh dengan gagasan bahwa mereka dapat memiliki ruang dan banyak karakter lucu lainnya dalam nama direktori mereka. (Spaces! Kembali ke masa saya, kami tidak memiliki ruang mewah!;))
Suatu hari, salah satu dari anak-anak itu akan menjalankan skrip Anda dengan $DIRECTORY
diatur ke "My M0viez"
dan skrip Anda akan meledak. Anda tidak menginginkan itu. Jadi gunakan ini.
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Perhatikan tes -d dapat menghasilkan beberapa hasil yang mengejutkan:
$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory
File di bawah: "Kapan sebuah direktori bukan sebuah direktori?" Jawabannya: "Ketika symlink ke direktori." Tes yang sedikit lebih teliti:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
Anda dapat menemukan informasi lebih lanjut di manual Bash tentang ekspresi kondisional Bash dan [
perintah builtin dan [[
komandemen majemuk .
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... atau, untuk satu perintah yang bekerja pada kedua tautan & direktori:rm -r tmpdir
Saya menemukan versi braket ganda dari test
membuat tes logika menulis lebih alami:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
if [[ -d "$TARFILE" ]]
saya mendapatkan [[: tidak ditemukan
[[ ]]
didukung, tetapi sebenarnya tidak memberikan fungsionalitas yang berbeda [ ]
. Jika portabilitas menjadi perhatian, patuhi [ ]
dan gunakan solusi yang diperlukan.
Bentuk lebih pendek:
[ -d "$DIR" ] && echo "Yes"
if $dir is a dir, then echo "yes"
:? Sedikit penjelasan akan membantu :)
cmd && other
adalah singkatan umum untuk if cmd; then other; fi
- ini bekerja dengan sebagian besar bahasa pemrograman yang mendukung logika Boolean, dan dikenal sebagai evaluasi hubung singkat .
set -e
(yang merupakan praktik terbaik pemrograman shell ).
[ -d "$DIR" ]
dicentang (diikuti oleh && echo Yes
), jadi saya percaya set -e
tidak ada bedanya dengan perilaku skrip (yaitu jika tes gagal, skrip berlanjut secara normal).
Untuk memeriksa apakah ada direktori, Anda dapat menggunakan if
struktur sederhana seperti ini:
if [ -d directory/path to a directory ] ; then
# Things to do
else #if needed #also: elif [new condition]
# Things to do
fi
Anda juga dapat melakukannya dengan negatif:
if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory
Catatan : Hati-hati. Sisakan ruang kosong di kedua sisi kurung buka dan tutup.
Dengan sintaks yang sama Anda dapat menggunakan:
-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
Skrip sederhana untuk menguji apakah direktori atau file ada atau tidak:
if [ -d /home/ram/dir ] # For file "if [-f /home/rama/file]"
then
echo "dir present"
else
echo "dir not present"
fi
Script sederhana untuk memeriksa apakah direktori ada atau tidak:
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
Script di atas akan memeriksa apakah direktori ada atau tidak
$?
jika perintah terakhir adalah sukses ia mengembalikan "0", jika tidak nilai nol. Misalkan tempdir
sudah ada. Maka mkdir tempdir
akan memberikan kesalahan seperti di bawah ini:
mkdir: tidak dapat membuat direktori 'tempdir': File ada
Anda dapat menggunakan test -d
(lihat man test
).
-d file
Benar jika file ada dan merupakan direktori.
Sebagai contoh:
test -d "/etc" && echo Exists || echo Does not exist
Catatan: test
Perintah ini sama dengan ekspresi kondisional [
(lihat man [
:), jadi ini portabel di skrip shell.
[
- Ini adalah sinonim untuktest
builtin, tetapi argumen terakhir harus, menjadi literal]
, agar sesuai dengan pembukaan[
.
Untuk opsi yang mungkin atau bantuan lebih lanjut, periksa:
help [
help test
man test
atau man [
Atau untuk sesuatu yang sama sekali tidak berguna:
[ -d . ] || echo "No"
Inilah ungkapan yang sangat pragmatis:
(cd $dir) || return # Is this a directory,
# and do we have access?
Saya biasanya membungkusnya dalam suatu fungsi:
can_use_as_dir() {
(cd ${1:?pathname expected}) || return
}
Atau:
assert_dir_access() {
(cd ${1:?pathname expected}) || exit
}
Yang menyenangkan tentang pendekatan ini adalah saya tidak perlu memikirkan pesan kesalahan yang baik.
cd
akan memberi saya pesan satu baris standar untuk kesalahan standar . Itu juga akan memberi lebih banyak informasi daripada yang bisa saya berikan. Dengan melakukan bagian cd
dalam subkulit ( ... )
, perintah tidak mempengaruhi direktori pemanggil saat ini. Jika direktori ada, subkulit ini dan fungsinya hanyalah larangan.
Berikutnya adalah argumen bahwa kita lolos ke cd
: ${1:?pathname expected}
. Ini adalah bentuk substitusi parameter yang lebih rumit yang dijelaskan secara lebih rinci di bawah ini.
Tl; dr: Jika string yang melewati fungsi ini kosong, kami kembali keluar dari subkulit ( ... )
dan kembali dari fungsi dengan pesan kesalahan yang diberikan.
Mengutip dari ksh93
halaman manual:
${parameter:?word}
Jika
parameter
disetel dan bukan nol maka gantilah nilainya; jika tidak, cetakword
dan keluar dari shell (jika tidak interaktif). Jikaword
dihilangkan maka pesan standar dicetak.
dan
Jika titik dua
:
dihilangkan dari ekspresi di atas, maka shell hanya memeriksa apakah parameter diatur atau tidak.
Ungkapan di sini adalah khusus untuk dokumentasi shell, seperti word
dapat merujuk pada string yang masuk akal, termasuk spasi.
Dalam kasus khusus ini, saya tahu bahwa pesan kesalahan standar 1: parameter not set
tidak cukup, jadi saya memperbesar jenis nilai yang kita harapkan di sini - pathname
direktori.
Catatan filosofis:
Shell bukan bahasa yang berorientasi objek, jadi pesannya mengatakan pathname
, bukan directory
. Pada level ini, saya lebih suka membuatnya tetap sederhana - argumen untuk suatu fungsi hanyalah string.
test -d
seperti yang dijelaskan oleh @Grundlefleck.
test -d /unreadable/exists
akan gagal, bahkan jika ada argumen.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
Kode di atas memeriksa apakah direktori tersebut ada dan apakah dapat ditulis.
DIRECTORY=/tmp
if [ -d "$DIRECTORY" ]; then
echo "Exists"
fi
space
setelah [
-> [`` -d . saya mendapat kesalahan karena ruang yang hilang
Ketikkan kode ini pada prompt Bash:
if [ -d "$DIRECTORY" ]; then
# If true this block of code will execute
fi
find
Periksa keberadaan folder dalam sub-direktori:
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
Periksa keberadaan satu atau beberapa folder berdasarkan pola dalam direktori saat ini:
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
Keduanya kombinasi. Dalam contoh berikut, ia memeriksa keberadaan folder di direktori saat ini:
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'
. Apakah Anda keberatan jika saya menambahkan dalam jawaban Anda trik ini? Cheers;)
Sebenarnya, Anda harus menggunakan beberapa alat untuk mendapatkan pendekatan antipeluru:
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
Tidak perlu khawatir tentang spasi dan karakter khusus selama Anda menggunakannya "${}"
.
Catatan yang [[]]
tidak semudah portabel []
, tetapi karena kebanyakan orang bekerja dengan versi modern Bash (karena bagaimanapun, kebanyakan orang bahkan tidak bekerja dengan baris perintah :-p), manfaatnya lebih besar daripada masalah.
Sudahkah Anda mempertimbangkan untuk melakukan apa saja yang ingin Anda lakukan di dalam if
daripada melihat sebelum melompat?
Yaitu, jika Anda ingin memeriksa keberadaan direktori sebelum Anda memasukkannya, coba lakukan ini:
if pushd /path/you/want/to/enter; then
# Commands you want to run in this directory
popd
fi
Jika jalur yang Anda berikan pushd
ada, Anda akan memasukkannya dan itu akan keluar dengan 0
, yang berarti then
bagian dari pernyataan akan dieksekusi. Jika tidak ada, tidak ada yang terjadi (selain beberapa output yang mengatakan direktori tidak ada, yang mungkin merupakan efek samping yang bermanfaat untuk debugging).
Tampaknya lebih baik dari ini, yang mengharuskan Anda mengulangi sendiri:
if [ -d /path/you/want/to/enter ]; then
pushd /path/you/want/to/enter
# Commands you want to run in this directory
popd
fi
Hal yang sama bekerja dengan cd
, mv
, rm
, dll ... jika Anda mencoba mereka pada file yang tidak ada, mereka akan keluar dengan kesalahan dan mencetak pesan yang mengatakan itu tidak ada, dan Anda then
blok akan dilewati. Jika Anda mencobanya pada file yang ada, perintah akan menjalankan dan keluar dengan status 0
, yang memungkinkan then
blok Anda untuk dieksekusi.
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
NB: Mengutip variabel adalah praktik yang baik.
Penjelasan:
-d
: periksa apakah itu direktori-L
: periksa apakah itu tautan simbolisUntuk memeriksa lebih dari satu direktori gunakan kode ini:
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
Periksa apakah direktori ada, buat yang lain:
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
mkdir -p "$DIRECTORY"
untuk efek yang sama.
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Jawaban ini dibungkus sebagai skrip shell
$ 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";
Menggunakan -e
cek akan memeriksa file dan ini termasuk direktori.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
Sesuai komentar Jonathan :
Jika Anda ingin membuat direktori dan belum ada, maka teknik paling sederhana adalah menggunakan mkdir -p
yang membuat direktori - dan direktori yang hilang di jalur - dan tidak gagal jika direktori sudah ada, sehingga Anda bisa melakukan semuanya sekaligus dengan:
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
Ini tidak sepenuhnya benar ...
Jika Anda ingin pergi ke direktori itu, Anda juga perlu memiliki hak eksekusi pada direktori. Mungkin Anda perlu memiliki hak tulis juga.
Karena itu:
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
Gunakan file
programnya. Mempertimbangkan semua direktori juga file di Linux, mengeluarkan perintah berikut akan cukup:
file $directory_name
Memeriksa file yang tidak ada: file blah
Keluaran: cannot open 'blah' (No such file or directory)
Memeriksa direktori yang ada: file bluh
Keluaran: bluh: directory
The ls
perintah dalam hubungannya dengan -l
(panjang daftar) kembali option atribut informasi tentang file dan direktori.
Khususnya karakter pertama dari ls -l
output biasanya a d
atau a -
(dash). Dalam kasus d
yang terdaftar adalah direktori pasti.
Perintah berikut hanya dalam satu baris akan memberi tahu Anda jika ISDIR
variabel yang diberikan berisi lintasan ke direktori atau tidak:
[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
Penggunaan praktis:
[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;
Jika Anda ingin memeriksa apakah ada direktori, terlepas dari apakah itu direktori asli atau symlink, gunakan ini:
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
Penjelasan: Perintah "ls" memberikan kesalahan "ls: / x: Tidak ada file atau direktori" jika direktori atau symlink tidak ada, dan juga menetapkan kode kembali, yang dapat Anda ambil melalui "$?", Ke non -null (biasanya "1"). Pastikan Anda memeriksa kode kembali secara langsung setelah memanggil "ls".
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"
Jika masalah ditemukan dengan salah satu pendekatan yang diberikan di atas:
Dengan ls
perintah; kasus-kasus ketika direktori tidak ada - pesan kesalahan ditampilkan
[[ `ls -ld SAMPLE_DIR| grep ^d | wc -l` -eq 1 ]] && echo exists || not exists
-ksh: tidak: tidak ditemukan [Tidak ada file atau direktori]
Ada solusi hebat di luar sana, tetapi pada akhirnya setiap skrip akan gagal jika Anda tidak berada di direktori yang benar. Jadi kode seperti ini:
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
akan mengeksekusi dengan sukses hanya jika pada saat eksekusi Anda berada di direktori yang memiliki subdirektori yang kebetulan Anda periksa.
Saya memahami pertanyaan awal seperti ini: untuk memverifikasi apakah ada direktori terlepas dari posisi pengguna dalam sistem file. Jadi menggunakan perintah 'find' mungkin melakukan trik:
dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d
Solusi ini bagus karena memungkinkan penggunaan wildcard, fitur yang berguna saat mencari file / direktori. Satu-satunya masalah adalah bahwa, jika direktori yang dicari tidak ada, perintah 'temukan' tidak akan mencetak apa pun ke output standar (bukan solusi elegan untuk seleraku) dan akan tetap memiliki jalan keluar nol. Mungkin seseorang bisa memperbaiki ini.
locate
tetapi tidak bagus untuk hal lain ...
--
sangat dianjurkan (penanda opsi akhir). Jika tidak, jika variabel Anda berisi sesuatu yang terlihat seperti opsi, skrip akan gagal seperti halnya spasi.