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:
#!/bin/bash
count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo true
fi
ls -l
, sử dụng câu trả lời của tôils -1
ls -1
sẽ in một dòng cho mỗi tập tin
\n
(và vâng, điều đó hợp lệ trong tên tệp).
#/bin/bash
myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then
echo true
else
echo false
fi
${#myarray[@]}
bằng 1
ls -1 *.py
thay vì tìm
Đ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
if ls *.flac >/dev/null 2>&1; then ... fi;
shopt -s nullglob
if [[ -n $(echo *.flac) ]] # or [ -n "$(echo *.flac)" ]
then
echo true
fi
Bạn cần phải thận trọng xem lá cờ nào bạn đưa vào if
tuyê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 -f
hạn chế đối if
với các tệp thông thường, trong khi -e
nó 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ư -d
cho 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 *.flac
trả về nhiều hơn một tệp. Trong trường hợp đó, hãy thử gói if
thử 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ể break
sử 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.
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ố"
"$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ị.
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.
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
[
(trái ngược với loại phổ biến hơn [[
) không ngăn cản sự xuất hiện.
shopt -s nullglob
set -- $(echo *.ext)
if [ "${#}" -gt 0 ];then
echo "got file"
fi
-ge
thay 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ẽ để *.ext
nguyên chuỗi , vì vậy bạn vẫn sẽ nhận được một "kết quả".
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ở nullglob
cài đặt hiện tại của bạn ).
Đâ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_any
sử 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 ./*.flac
thay vì chỉ *.flac
trong cuộc gọi đến have_any
là để tránh các vấn đề gây ra bởi các tệp có tên như --help
.
Để 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 đó N
cờ ( NULL_GLOB
tùy chọn) để buộc chuỗi được tạo trống trong trường hợp không có khớp.
Đâ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ử đ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))
Đ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