Lệnh hiển thị một thông báo tùy ý nếu một tệp cụ thể tồn tại


11

Có lệnh nào để hiển thị thông báo Có Có hay không nếu một tệp cụ thể tồn tại? Không cần phải cung cấp chức năng nếu tập tin không tồn tại.

Câu trả lời:


25

Sử dụng Bash one-liner đơn giản này:

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

Các -eđánh giá lại séc là true nếu FILENAMEtồn tại, không có vấn đề gì nó là gì (tập tin, thư mục, liên kết, thiết bị, ...).

Nếu bạn chỉ muốn kiểm tra các tệp thông thường, hãy sử dụng -fthay thế, như @Arronical đã nói.


18
[ -e FILENAME ] && echo Yes
Zeb McCorkle

@ZebMcCorkle Đúng, nó cũng hoạt động. Bạn có thể gửi câu trả lời riêng biệt.
Chỉ huy Byte

3
Nếu FILENAMElà một mở rộng biến, hoặc chứa bất kỳ ký tự đặc biệt nào, thì đừng quên trích dẫn nó. ví dụ trong một kịch bản , [ -e "$1" ] && echo Yes.
Peter Cordes

@PeterCordes nếu bạn đang sử dụng bash, bạn có thể sử dụng [[]]thay vì trích dẫn biến.
Holloway

1
@Holloway: yup, nhưng đôi khi bạn cần viết các tập lệnh di động chỉ yêu cầu POSIX sh. Đó là lý do tại sao tôi đưa ra một phiên bản an toàn của điều này thay vì hạ thấp nó và nâng cao câu trả lời bash. Cũng lưu ý rằng không phải là vấn đề khi trích dẫn mở rộng bên trong [[ ]], luôn luôn trích dẫn là một thói quen tốt cho người mới bắt đầu không nhớ các quy tắc đặc biệt cho bên trong [[ ]]toán tử hoặc cho bối cảnh số học.
Peter Cordes

10

Bạn có thể sử dụng tập lệnh đơn giản này:

#!/bin/bash

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

Lưu nó như file-exists.sh. Sau đó, trong Terminal, gõ chmod +x file-exists.sh.

Sử dụng nó như: ./file-exists.sh FILEnơi bạn thay thế FILEbằng tệp bạn muốn kiểm tra, ví dụ:

./file-exists.sh file.txt

Nếu file.txttồn tại, Yessẽ được in ra Terminal và chương trình sẽ thoát với trạng thái 0 (thành công). Nếu tệp không tồn tại, sẽ không có gì được in và chương trình sẽ thoát với trạng thái 1 (thất bại).

Nếu bạn tò mò tại sao tôi lại đưa vào exitlệnh, hãy đọc tiếp ...


Có chuyện gì với exitlệnh?

exitgây ra chấm dứt quá trình bình thường. Điều này có nghĩa là, về cơ bản: nó dừng tập lệnh. Nó chấp nhận một tham số (số) tùy chọn sẽ là trạng thái thoát của tập lệnh đã gọi nó.

Trạng thái thoát này cho phép các tập lệnh khác của bạn sử dụng file-existstập lệnh của bạn và là cách họ biết tệp có tồn tại hay không.

Một ví dụ đơn giản đặt cái này để sử dụng là tập lệnh này (lưu nó dưới dạng 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

Làm như bình thường chmod +x file-exists-cli.shvà sau đó chạy nó : ./file-exists-cli.sh. Bạn sẽ thấy một cái gì đó như thế này:

Tệp tồn tại ( exit 0):

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

Tệp không tồn tại ( exit 1):

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

2
Tốt, nhưng bạn sẽ trích dẫn tài liệu tham khảo biến như "$1". Nếu nó có khoảng trắng trong đó, nó sẽ vỡ mà không có dấu ngoặc kép và những điều tồi tệ khác có thể xảy ra.
Joe

9

Trong bash shell trên dòng lệnh.

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

Điều này sử dụng toán tử điều kiện bash -fvà kiểm tra xem tệp có tồn tại và là một tệp thông thường hay không. Nếu bạn muốn kiểm tra bất kỳ tập tin bao gồm các thư mục và liên kết thì hãy sử dụng -e.

Đây là một nguồn tài nguyên tuyệt vời cho bash điều kiện.


1
Tại sao niềng răng đôi?
Chỉ huy Byte

1
Tôi không phải là người hâm mộ testở định dạng ban đầu, tôi biết đó là quá mức cần thiết, nhưng đó là thói quen của tôi.
Arronical

7
@ByteCommander: niềng răng đôi thường tốt hơn so với niềng răng đơn. Chúng là một phần của cú pháp shell (thay vì gọi [lệnh, thường gọi lệnh dựng sẵn.) Chúng sửa lỗi không nhất quán và hành vi ngu ngốc của phiên bản nẹp đơn. [Nội dung tích hợp vẫn còn để tương thích, nhưng tôi không thấy bất kỳ lý do chính đáng nào để sử dụng nó trong mã bash mới. (Nếu bạn cần viết các tập lệnh tuân thủ POSIX có thể chạy trên các shell cổ hoặc thứ gì đó, thì khác.)
Nick Matteo

@kundor: Mặc dù vậy, hầu hết đều đồng ý, công bằng, " [thường gọi là dựng sẵn" là không rõ ràng. type -a [đối với tôi liệt kê "shell dựng", sau đó " /usr/bin/[."
wchargein

1
@wchargein: Tôi sợ tôi không hiểu bạn đang làm gì. typeKết quả của bạn dường như chứng thực những gì tôi nói, phải không?
Nick Matteo

5

Lệnh ngắn nhất để làm những gì bạn muốn là:

test -e FILENAME && echo Yes

test -esẽ kiểm tra xem tên đã cho có tồn tại trong hệ thống tệp hay không. (Bạn chỉ có thể sử dụng test -fđể giới hạn các tệp thông thường. Xem man testthêm.)

Nếu điều kiện đưa ra đánh giá là đúng, thì testsẽ trả về trạng thái thoát thành công (nếu không, nó sẽ trả về trạng thái lỗi). Chúng tôi kết hợp hai lệnh bằng cách sử dụng &&, có nghĩa là "thực hiện lệnh tiếp theo nếu lệnh trước đó thoát với trạng thái thành công". Lệnh tiếp theo chỉ đơn giản là in Yestrên đầu ra tiêu chuẩn; trong trường hợp vỏ tương tác, trên thiết bị đầu cuối.

Điều này tránh các tài liệu văn bản bổ sung của một iftuyên bố, nhưng cho kết quả tương tự. Sử dụng &&(hoặc ngược lại, ||) để liên kết các lệnh với nhau hoạt động tốt khi chỉ có một lệnh duy nhất được tham gia. Nếu bạn muốn làm nhiều hơn là thực thi một lệnh để đáp ứng với trạng thái thoát của một lệnh, thì việc sử dụng ifcú pháp nhanh chóng trở nên dễ đọc hơn nhiều.

Như đã chỉ ra trong các câu trả lời khác, ifcấu trúc kiểu tương đương sẽ là:

if test -e FILENAME; then echo Yes; fi

Hay cách khác:

if test -e FILENAME
then
    echo Yes
fi

Đối với các mục đích này, [testlà tương đương, ngoại trừ [yêu cầu chấm dứt ].


4

Để xử lý loại câu hỏi này có nhiều cách và đây là một cách khác: sử dụng findlệnh với -execcờ. Đường dẫn đến tệp có thể được chia thành hai phần find /etcđặt thư mục và -name FILENAMEchỉ định tên tệp (duh!). -maxdepthsẽ chỉ tiếp tục findlàm việc với /etcthư mục và sẽ không rơi vào thư mục con

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

Một cách khác, thông qua stat:

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

Và thay thế thông qua 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'

Hoặc một dòng lệnh ngắn thay thế:

 python -c "from os.path import exists; print 'Yes' if exists('/etc/fstab') else '' "
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.