Kiểm tra xem một loại tệp / phần mở rộng nhất định có tồn tại trong thư mục hay không


84

Bạn sẽ làm thế nào về việc cho biết liệu các tệp của một tiện ích mở rộng cụ thể có hiện diện trong một thư mục hay không, với bash?

Cái gì đó như

if [ -e *.flac ]; then 
echo true; 
fi 

Câu trả lời:


104
#!/bin/bash

count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then 
echo true
fi 

9
Này Thomas, làm thế nào về việc thêm một giải pháp tốt hơn cho câu hỏi thay vì chỉ một lời tán thành.
JeremyWeir

8
Cũng Thomas, ví dụ của bạn về việc tại sao không sử dụng nó được sử dụng ls -l, sử dụng câu trả lời của tôils -1
JeremyWeir

10
Và, câu trả lời này không được phân tích đầu ra, nó chỉ được đếm các dòng đầu ra, và tôi gần như chắc chắn ngay cả khi có những nhân vật kỳ lạ trong một tên tập tin, ls -1sẽ in một dòng cho mỗi tập tin
JeremyWeir

2
Đếm dòng đang phân tích cú pháp. Và nó sẽ trả về một số không chính xác nếu bất kỳ tệp nào chứa \n(và vâng, điều đó hợp lệ trong tên tệp).
marcelm

1
Sau đó, hãy cầu nguyện cho chúng tôi biết, ký tự phép thuật nào sẽ phải có trong tên của một tệp tin để làm cho số dòng không có giá trị?
yeoman

27
#/bin/bash

myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then 
    echo true 
else 
    echo false
fi

5
Cái này rất hay vì bạn thực sự có thể làm gì đó với các tệp sau khi tìm thấy chúng.
ephsmith

+1 để đóng gói con chạy tìm trong dấu ngoặc đơn để biến myarray thành một biến mảng. Ngược lại, nếu tìm thấy kết quả trả lại không ${#myarray[@]}bằng 1
shaffooo

cũng có thể đơn giản hóa bằng cách sử dụng ls -1 *.pythay vì tìm
JrBenito

Nếu bất kỳ tệp nào có khoảng trắng trong tên, điều này sẽ được tính là một phiên bản là hai.
Jon Griffith

16

Điều này sử dụng ls (1), nếu không có tệp flac nào tồn tại, ls báo lỗi và tập lệnh thoát; ngược lại, tập lệnh vẫn tiếp tục và các tệp có thể được xử lý

#! /bin/sh
ls *.flac  >/dev/null || exit
## Do something with flac files here

4
Để có thêm khoảng lặng, hãy chuyển hướng 2> & 1.
Jasper

6
Phiên bản if:if ls *.flac >/dev/null 2>&1; then ... fi;
Josiah Yoder


4

Bạn cần phải thận trọng xem lá cờ nào bạn đưa vào iftuyên bố của mình và nó liên quan như thế nào đến kết quả bạn muốn.

Nếu bạn chỉ muốn kiểm tra các tệp thông thường chứ không phải các loại mục nhập hệ thống tệp khác thì bạn sẽ muốn thay đổi khung mã của mình thành:

if [ -f file ]; then
echo true;
fi

Việc sử dụng các -fhạn chế đối ifvới các tệp thông thường, trong khi -enó mở rộng hơn và sẽ phù hợp với tất cả các loại mục nhập hệ thống tệp. Tất nhiên có các tùy chọn khác như -dcho thư mục, v.v. Xem http://tldp.org/LDP/abs/html/fto.html để có danh sách tốt.

Như đã chỉ ra bởi @msw, test(tức là [) sẽ bị nghẹt thở nếu bạn thử và nạp nó nhiều hơn một đối số. Điều này có thể xảy ra trong trường hợp của bạn nếu cầu cho *.flactrả về nhiều hơn một tệp. Trong trường hợp đó, hãy thử gói ifthử nghiệm của bạn trong một vòng lặp như:

for file in ./*.pdf
do
    if [ -f "${file}" ]; then
    echo 'true';
    break
    fi
done

Bằng cách này, bạn có thể breaksử dụng phiên bản đầu tiên của phần mở rộng tệp mà bạn muốn và có thể tiếp tục với phần còn lại của tập lệnh.


1
ngoại trừ test(còn gọi là [) phàn nàn nếu mẫu mở rộng thành nhiều hơn một tệp: "toán tử nhị phân được mong đợi" hoặc "quá nhiều đối số"
msw 4/10/10

1
@msw - cảm ơn, tôi thậm chí không nghĩ đến vấn đề đó. Tôi đã cố gắng sửa đổi câu trả lời của mình để tính đến nó.
dtlussier

Bạn nên trích dẫn biến, tức là sử dụng "$file", vì tên tệp có thể chứa một số ký tự không hợp lệ, như dấu cách hoặc dấu hoa thị.
Roman Cheplyaka

3
#!/bin/bash
files=$(ls /home/somedir/*.flac 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
echo "Some files exists."
else
echo "No files with that extension."
fi

3

Giải pháp hàng đầu (if [ -e *.flac ];)không hoạt động với tôi, đưa ra:[: too many arguments

if ls *.flac >/dev/null 2>&1; sau đó nó sẽ hoạt động.


3

Bạn có thể sử dụng -f để kiểm tra xem các tệp thuộc một loại cụ thể có tồn tại hay không:

#!/bin/bash

if [ -f *.flac ] ; then
   echo true
fi 

Điều này hoạt động nhưng bạn đang chôn dấu led - lý do nó hoạt động là vì dấu ngoặc đơn [(trái ngược với loại phổ biến hơn [[) không ngăn cản sự xuất hiện.
Adrian Petrescu

2
   shopt -s nullglob
   set -- $(echo *.ext)
    if [ "${#}" -gt 0 ];then
      echo "got file"
    fi

Cái này sai. Đầu tiên, bạn có thể có ý định -gethay vì -gt, vì nếu không mã của bạn sẽ không phát hiện ra tệp đơn. Thứ hai, nếu không có tệp nào phù hợp với mẫu, bất kỳ trình bao phù hợp nào sẽ để *.extnguyên chuỗi , vì vậy bạn vẫn sẽ nhận được một "kết quả".
Roman Cheplyaka

$ # là 1 đối với tệp singe và 0 đối với tệp không có.
frayser

1

chỉ bash:

any_with_ext () ( 
    ext="$1"
    any=false
    shopt -s nullglob
    for f in *."$ext"; do
        any=true
        break
    done
    echo $any 
)

if $( any_with_ext flac ); then
    echo "have some flac"
else 
    echo "dir is flac-free"
fi

Tôi sử dụng dấu ngoặc đơn thay vì dấu ngoặc nhọn để đảm bảo rằng một vỏ con được sử dụng (không muốn cản trở nullglobcài đặt hiện tại của bạn ).


1

Đây là một giải pháp không sử dụng lệnh bên ngoài (tức là không ls) mà thay vào đó là một hàm shell. Đã kiểm tra trong bash:

shopt -s nullglob
function have_any() {
    [ $# -gt 0 ]
}

if have_any ./*.flac; then
    echo true
fi

Hàm have_anysử dụng $#để đếm các đối số của nó và [ $# -gt 0 ]sau đó kiểm tra xem có ít nhất một đối số hay không. Việc sử dụng ./*.flacthay vì chỉ *.flactrong cuộc gọi đến have_anylà để tránh các vấn đề gây ra bởi các tệp có tên như --help.


1

Để hoàn thành, với zsh:

if [[ -n *.flac(#qN) ]]; then
  echo true
fi

Điều này được liệt kê ở cuối phần Biểu thức có điều kiện trong sổ tay zsh. Vì [[vô hiệu hóa globbing tên tệp, chúng ta cần buộc tạo tên tệp bằng cách sử dụng (#q)ở cuối chuỗi cầu nối, sau đó Ncờ ( NULL_GLOBtùy chọn) để buộc chuỗi được tạo trống trong trường hợp không có khớp.


1

Đây là một giải pháp khá đơn giản:

if [ "$(ls -A | grep -i \\.flac\$)" ]; then echo true; fi

Như bạn có thể thấy, đây chỉ là một dòng mã, nhưng nó hoạt động đủ tốt. Nó sẽ hoạt động với cả bash và shell tuân thủ posix như dấu gạch ngang. Nó cũng không phân biệt chữ hoa chữ thường và không quan tâm đến loại tệp nào (thông thường, liên kết biểu tượng, thư mục, v.v.), điều này có thể hữu ích nếu bạn có một số liên kết tượng trưng hoặc thứ gì đó.


tôi thích điều này vì ls -AR thực hiện tìm kiếm đệ quy. tốt cho việc tìm kiếm nội dung của kho lưu trữ zip sau khi giải nén.
justin cress

0

Tôi đã thử điều này:

if [ -f *.html ]; then
    echo "html files exist"
else
    echo "html files dont exist"
fi

Tôi đã sử dụng đoạn mã này mà không gặp bất kỳ sự cố nào đối với các tệp khác, nhưng đối với tệp html, tôi đã gặp lỗi :

[: too many arguments

Sau đó, tôi đã thử giải pháp đếm của @ JeremyWeir, giải pháp này phù hợp với tôi.

Hãy nhớ rằng bạn sẽ phải đặt lại số lượng nếu bạn đang làm điều này trong một vòng lặp:

count=$((0))

0

Điều này sẽ hoạt động trong bất kỳ trình bao giống như đã sinh nào ngoài đó:

if [ "$(find . -maxdepth 1 -type f | grep -i '.*\.flac$')" ]; then
    echo true
fi

Điều này cũng hoạt động với GNU find, nhưng IDK nếu điều này tương thích với các triển khai khác của find:

if [ "$(find . -maxdepth 1 -type f -iname \*.flac)" ]; then
    echo true
fi
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.