nếu lệnh trong find -exec


9

Tôi chỉ cố gắng liệt kê tất cả các thư mục và tệp trong thư mục hiện tại và cũng viết nếu chúng là tệp hoặc thư mục với lệnh sau:

find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;

Tôi biết đó là một lệnh ngớ ngẩn, tôi có thể sử dụng những thứ khác như -type fhoặc -type d, nhưng tôi muốn tìm hiểu lý do tại sao đoạn mã đó không hoạt động như tôi mong đợi. Nó chỉ in thư mục cho tất cả chúng. Ví dụ: trong khi đầu ra findlà:

.
./dir
./dir/file

đầu ra của mã của tôi là:

. : directory
./dir : directory
./dir/file : directory

Và đầu ra của

echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`

dir/file : file

Tôi đang làm việc Ubuntu 14.10và sử dụngfind (GNU findutils) 4.4.2


1
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
Costas

1
Cảm ơn @Costas nhưng tôi biết rằng sử dụng bash hoặc sh tôi có thể đạt được mục tiêu ban đầu của mình, nhưng bây giờ tôi muốn hiểu tại sao nếu hành xử khác với tham số exec.
Esref

Đặt các đối số vào dấu ngoặc kép "{}". Tại sao bạn sử dụng echohai lần?
Costas

Tôi đã thử điều đó và nó cho đầu ra tương tự. tìm -exec echo echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi\;
Esref

Câu trả lời:


13

Đầu tiên, đoạn mã của bạn thực thi lệnh

echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi

bởi vì nó cần đầu ra của nó để đánh giá sự thay thế lệnh. Vì không có tệp có tên {}, điều này tạo ra đầu ra

{} :
directory

Sau đó, các findlệnh được thực thi với các đối số -exec, echo, {}, :, directory, vì vậy cho mỗi tập tin, nó kết quả đầu ra tên tập tin sau đó là một không gian và : directory.

Những gì bạn thực sự muốn làm là thực thi đoạn mã shell echo {} :; …trên mỗi tệp được tìm thấy bởi find. Đoạn mã này phải được thực thi bởi một vỏ được sinh ra bởi find, chứ không phải bởi vỏ bắt đầu find, vì nó đang nhận dữ liệu từ findtrên dòng lệnh của nó. Do đó, bạn cần phải hướng dẫn findđể chạy shell:

find -exec sh -c 'echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi' \;

Điều này là tốt hơn, nhưng vẫn không đúng. Nó sẽ hoạt động với một số findtriển khai (không phải tất cả) nếu tên tệp của bạn không chứa bất kỳ ký tự đặc biệt nào, nhưng vì bạn đang nội suy tên tệp trong tập lệnh shell, bạn cho phép tên tệp thực thi các lệnh shell tùy ý, ví dụ: nếu bạn có một tập tin được gọi $(rm -rf /)thì lệnh rm -rf /sẽ được thực thi. Để truyền tên tệp cho tập lệnh, chuyển chúng dưới dạng đối số riêng biệt.

Ngoài ra đầu tiên echoin một dòng mới sau dấu hai chấm. Sử dụng echo -n(nếu vỏ của bạn hỗ trợ nó) hoặc printfđể tránh điều này.

find -exec sh -c 'printf "%s :" "$0"; if [ -f "$0" ]; then echo file; else echo directory; fi' {} \;

Bạn có thể sử dụng -exec … {} +để nhóm các lệnh shell, nhanh hơn.

find -exec sh -c 'for x; do printf "%s :" "$x"; if [ -f "$x" ]; then echo file; else echo directory; fi; done' _ {} +

3

Một cách khác để thực hiện if; then; else; ficùng với findlà:

find |
while read p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done

1
Dung dịch mát. Nó tránh các mẫu trích dẫn phức tạp và các biến chứng dưới vỏ. Trước đây bạn có thể đã xác định hàm shell và thực thi nó trên các tệp khớp với điều kiện "nếu".
gerlos
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.