Perintah untuk menampilkan pesan arbitrer jika ada file tertentu

11

Apakah ada perintah untuk menampilkan pesan "Ya" jika ada file tertentu? Tidak perlu memberikan fungsionalitas jika file tidak ada.

james
sumber

Jawaban:

25

Gunakan Bash satu-liner sederhana ini:

if [ -e FILENAME ] ; then echo Yes ; fi

The -ecek mengevaluasi true jika FILENAMEada, tidak peduli apa itu (file, direktori, link perangkat, ...).

Jika Anda hanya ingin memeriksa file biasa, gunakan -fsaja, seperti yang dikatakan @Arronical .

Komandan Byte
sumber
18
[ -e FILENAME ] && echo Yes
Zeb McCorkle
@ZebMcCorkle Benar, itu juga berfungsi. Anda dapat memposting itu sebagai jawaban terpisah.
Byte Commander
3
Jika FILENAMEekspansi variabel, atau berisi karakter khusus, maka jangan lupa untuk mengutipnya. misalnya dalam naskah [ -e "$1" ] && echo Yes,.
Peter Cordes
@PeterCordes jika Anda menggunakan bash, Anda dapat menggunakan [[dan ]]bukannya mengutip variabel.
Holloway
1
@Holloway: yup, tapi kadang-kadang Anda perlu menulis skrip portabel yang hanya membutuhkan POSIX sh. Itu sebabnya saya memberikan versi yang aman dari ini daripada downvoting dan upvot jawaban bash. Perhatikan juga bahwa tidak masalah untuk mengutip ekspansi di dalam [[ ]], selalu mengutip adalah kebiasaan yang baik untuk pemula yang tidak ingat aturan khusus untuk di dalam [[ ]]operator, atau untuk konteks aritmatika.
Peter Cordes
10

Anda dapat menggunakan skrip sederhana ini:

#!/bin/bash

if [[ -f $1 ]]; then
    echo "Yes"
    exit 0
else
    exit 1
fi

Simpan sebagai file-exists.sh. Kemudian, di Terminal, ketik chmod +x file-exists.sh.

Gunakan seperti: ./file-exists.sh FILEtempat Anda mengganti FILEdengan file yang ingin Anda periksa, misalnya:

./file-exists.sh file.txt

Jika file.txtada, Yesakan dicetak ke Terminal, dan program akan keluar dengan status 0 (berhasil). Jika file tidak ada, tidak ada yang akan dicetak dan program akan keluar dengan status 1 (gagal).

Jika Anda penasaran mengapa saya memasukkan exitperintah, baca terus ...


Ada apa dengan exitperintahnya?

exitmenyebabkan pemutusan proses normal. Apa artinya ini, pada dasarnya: menghentikan skrip. Ini menerima parameter opsional (numerik) yang akan menjadi status keluar dari skrip yang memanggilnya.

Status keluar ini memungkinkan skrip Anda yang lain untuk menggunakan file-existsskrip Anda dan cara mereka mengetahui file itu ada atau tidak.

Contoh sederhana yang menggunakan ini adalah skrip ini (simpan sebagai file-exists-cli.sh):

#!/bin/bash

echo "Enter a filename and I will tell you if it exists or not: "
read FILE
# Run `file-exists.sh` but discard any output because we don't need it in this example
./file-exists.sh $FILE &>> /dev/null
# #? is a special variable that holds the exit status of the previous command
if [[ $? == 0 ]]; then
    echo "$FILE exists"
else
    echo "$FILE does not exist"
fi

Melakukan hal yang biasa chmod +x file-exists-cli.shdan kemudian menjalankannya: ./file-exists-cli.sh. Anda akan melihat sesuatu seperti ini:

File ada ( exit 0):

➜  ~ ./file-exists-cli.sh 
Enter a filename and I will tell you if it exists or not: 
booleans.py
booleans.py exists

File tidak ada ( exit 1):

➜  ~ ./file-exists-cli.sh
Enter a filename and I will tell you if it exists or not: 
asdf
asdf does not exist
grooveplex
sumber
2
Bagus, tetapi Anda harus mengutip referensi variabel suka "$1". Jika memiliki ruang putih di dalamnya, itu akan pecah tanpa tanda kutip dan hal-hal buruk lainnya dapat terjadi.
Joe
9

Di shell bash pada baris perintah.

if [[ -f /path/to/file ]]; then echo "Yes"; fi

Ini menggunakan operator kondisional bash -f, dan sedang memeriksa apakah file tersebut ada dan merupakan file biasa. Jika Anda ingin menguji file apa pun termasuk direktori dan tautan kemudian gunakan -e.

Ini adalah sumber yang bagus untuk persyaratan bash.

Arronikal
sumber
1
Mengapa kawat gigi ganda?
Byte Commander
1
Saya bukan penggemar testdalam format aslinya, saya tahu ini berlebihan, tapi itu kebiasaan saya.
Arronical
7
@ByteCommander: kawat gigi ganda umumnya lebih baik daripada kawat gigi tunggal. Mereka adalah bagian dari sintaks shell (alih-alih menjalankan [perintah, yang biasanya memanggil builtin.) Mereka mengoreksi inkonsistensi dan perilaku bodoh dari versi penjepit tunggal. [Builtin tetap untuk kompatibilitas, tapi saya tidak melihat alasan bagus untuk menggunakannya dalam kode bash baru. (Jika Anda perlu menulis skrip POSIX-compliant yang dapat berjalan di shell kuno atau sesuatu, itu berbeda.)
Nick Matteo
@kundor: Kebanyakan setuju, untuk bersikap adil, " [biasanya memanggil builtin" meragukan. type -a [bagi saya daftar "shell builtin", lalu " /usr/bin/[."
wchargin
1
@wchargin: Saya rasa saya tidak mengerti apa yang Anda maksud. typeHasil Anda tampaknya menguatkan apa yang saya katakan, bukan?
Nick Matteo
5

Perintah terpendek untuk melakukan apa yang Anda inginkan adalah:

test -e FILENAME && echo Yes

test -eakan menguji apakah nama yang diberikan ada di sistem file. (Anda dapat menggunakan test -funtuk membatasi hanya file biasa. Lihat man testlebih lanjut.)

Jika kondisi yang diberikan bernilai true, maka testmengembalikan status keluar yang berhasil (jika tidak mengembalikan status kegagalan). Kami menggabungkan dua perintah menggunakan &&, yang berarti "mengeksekusi perintah berikutnya jika perintah sebelumnya keluar dengan status sukses". Perintah selanjutnya hanya mencetak Yespada output standar; dalam kasus shell interaktif, di terminal.

Ini menghindari bahan tekstual tambahan dari sebuah ifpernyataan, namun memberikan hasil yang sama. Menggunakan &&(atau kebalikannya, ||) untuk mengikat perintah bekerja dengan baik ketika hanya satu perintah yang terlibat. Jika Anda ingin melakukan lebih dari satu perintah dalam menanggapi status keluar satu perintah, maka menggunakan ifsintaks dengan cepat menjadi jauh lebih mudah dibaca.

Seperti yang sudah ditunjukkan dalam jawaban lain, ifkonstruk gaya yang setara adalah:

if test -e FILENAME; then echo Yes; fi

atau sebagai alternatif:

if test -e FILENAME
then
    echo Yes
fi

Untuk tujuan ini, [dan testsetara, kecuali yang [menuntut penghentian ].

sebuah CVn
sumber
4

Untuk menguliti jenis pertanyaan ini ada beberapa cara, dan inilah satu lagi: gunakan findperintah dengan -execflag. Path ke file dapat dibagi menjadi dua bagian find /etcyang menetapkan direktori dan -name FILENAMEyang menentukan nama file (ya!). -maxdepthakan tetap findbekerja dengan /etcdirektori saja dan tidak akan turun ke subdirektori

adminx@L455D:~$ find /etc -maxdepth 1  -name passwd -exec printf "YES\n" \;
YES
adminx@L455D:~$ find /etc -maxdepth 1  -name passwd1 -exec printf "YES\n" \;
adminx@L455D:~$ 

Cara lain, melalui stat:

adminx@L455D:~$ stat /etc/passwd1 &>/dev/null && echo YES
adminx@L455D:~$ stat /etc/passwd &>/dev/null && echo YES
YES

Dan sebagai alternatif melalui python:

>>> import os
>>> if os.stat('/etc/passwd'): 
...    print 'YES'
... 
YES
>>> if os.stat('/etc/passwd1'): 
...    print 'YES'
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: '/etc/passwd1'

Atau alternatif baris perintah pendek:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Sergiy Kolodyazhnyy
sumber