[ad_1]
Các thư mục trên Linux cho phép bạn nhóm các tệp trong các bộ sưu tập riêng biệt, riêng biệt. Nhược điểm là nó trở nên tẻ nhạt khi di chuyển từ thư mục này sang thư mục khác để thực hiện một nhiệm vụ lặp đi lặp lại. Đây là cách để tự động hóa điều đó.
Tất cả Giới thiệu về Thư mục
Lệnh đầu tiên bạn học khi làm quen với Linux có thể là ls
nhưng cd
sẽ không bị bỏ xa sau nó. Hiểu các thư mục và cách di chuyển xung quanh chúng, đặc biệt là các thư mục con lồng nhau, là một phần cơ bản để hiểu cách Linux tự tổ chức và cách bạn có thể tổ chức công việc của mình thành các tệp, thư mục và thư mục con.
Nắm bắt khái niệm về một cây thư mục — và cách di chuyển giữa chúng — là một trong nhiều cột mốc quan trọng mà bạn vượt qua khi làm quen với bối cảnh của Linux. Sử dụng cd
với một đường dẫn đưa bạn đến thư mục đó. Các phím tắt như cd ~
hoặc cd
tự nó sẽ đưa bạn trở lại thư mục chính của bạn và cd ..
di chuyển bạn lên một cấp trong cây thư mục. Giản dị.
Tuy nhiên, không có một phương tiện đơn giản như nhau để chạy một lệnh trong tất cả các thư mục của cây thư mục. Có nhiều cách khác nhau để chúng ta có thể đạt được chức năng đó, nhưng không có lệnh Linux tiêu chuẩn nào dành riêng cho mục đích đó.
Một số lệnh, chẳng hạn như ls
có các tùy chọn dòng lệnh buộc chúng phải hoạt động đệ quy, nghĩa là chúng bắt đầu trong một thư mục và hoạt động theo phương pháp thông qua toàn bộ cây thư mục bên dưới thư mục đó. Vì ls
đó là -R
(đệ quy) tùy chọn.
Nếu bạn cần sử dụng lệnh không hỗ trợ đệ quy, bạn phải tự cung cấp chức năng đệ quy. Đây là cách để làm điều đó.
CÓ LIÊN QUAN: 37 lệnh quan trọng trong Linux bạn nên biết
Lệnh cây
Các tree
lệnh sẽ không giúp chúng ta thực hiện nhiệm vụ trong tầm tay, nhưng nó giúp bạn dễ dàng nhìn thấy cấu trúc của cây thư mục. Nó vẽ cây trong cửa sổ đầu cuối để chúng ta có thể có cái nhìn tổng quan tức thì về các thư mục và thư mục con tạo nên cây thư mục và vị trí tương đối của chúng trong cây.
Bạn sẽ cần cài đặt tree
.
Trên Ubuntu, bạn cần nhập:
sudo apt install tree
Trên Fedora, sử dụng:
sudo dnf install tree
Trên Manjaro, lệnh là:
sudo pacman -Sy tree
Sử dụng tree
không có tham số vẽ ra cây bên dưới thư mục hiện tại.
tree
Bạn có thể vượt qua một con đường để tree
trên dòng lệnh.
tree work
Các -d
(thư mục) tùy chọn loại trừ các tệp và chỉ hiển thị các thư mục.
tree -d work
Đây là cách thuận tiện nhất để có cái nhìn rõ ràng về cấu trúc của cây thư mục. Cây thư mục được hiển thị ở đây là cây được sử dụng trong các ví dụ sau. Có năm tệp văn bản và tám thư mục.
Không phân tích cú pháp đầu ra từ ls đến các thư mục Traverse
Suy nghĩ đầu tiên của bạn có thể là, nếu ls
có thể duyệt đệ quy một cây thư mục, tại sao không sử dụng ls
để làm điều đó và chuyển đầu ra thành một số lệnh khác phân tích cú pháp các thư mục và thực hiện một số hành động?
Phân tích cú pháp đầu ra của ls
được coi là thực hành xấu. Do khả năng trong Linux có thể tạo tên tệp và thư mục chứa tất cả các loại ký tự lạ, nên rất khó để tạo ra một trình phân tích cú pháp chung, chính xác.
Bạn có thể không bao giờ cố ý tạo một tên thư mục phi lý như thế này, nhưng có thể xảy ra sai sót trong tập lệnh hoặc ứng dụng.
Việc phân tích cú pháp các tên tệp và thư mục hợp pháp nhưng được coi là kém dễ xảy ra lỗi. Có những phương pháp khác mà chúng tôi có thể sử dụng an toàn hơn và mạnh mẽ hơn nhiều so với việc dựa vào việc diễn giải kết quả đầu ra của ls
.
Sử dụng lệnh find
Các find
lệnh có các khả năng đệ quy được tích hợp sẵn và nó cũng có khả năng chạy các lệnh cho chúng ta. Điều này cho phép chúng tôi xây dựng một lớp lót mạnh mẽ. Nếu đó là thứ mà bạn có khả năng muốn sử dụng trong tương lai, bạn có thể biến một lớp lót của mình thành một bí danh hoặc một hàm shell.
Lệnh này lặp một cách đệ quy qua cây thư mục, tìm kiếm các thư mục. Mỗi khi tìm thấy một thư mục, nó sẽ in ra tên của thư mục đó và lặp lại việc tìm kiếm bên trong thư mục đó. Sau khi hoàn thành việc tìm kiếm một thư mục, nó thoát khỏi thư mục đó và tiếp tục tìm kiếm trong thư mục mẹ của nó.
find work -type d -execdir echo "In:" {} ;
Bạn có thể xem theo thứ tự các thư mục được liệt kê, cách tìm kiếm tiến triển qua cây. Bằng cách so sánh kết quả đầu ra từ tree
lệnh đến đầu ra từ find
một lớp lót, bạn sẽ thấy cách find
lần lượt tìm kiếm từng thư mục và thư mục con cho đến khi gặp thư mục không có thư mục con. Sau đó, nó quay trở lại một cấp độ và tiếp tục tìm kiếm ở cấp độ đó.
Đây là cách tạo ra lệnh.
- tìm thấy: Các
find
yêu cầu. - công việc: Thư mục để bắt đầu tìm kiếm. Đây có thể là một đường dẫn.
- -loại d: Chúng tôi đang tìm kiếm các thư mục.
- -execdir: Chúng tôi sẽ thực thi một lệnh trong mỗi thư mục mà chúng tôi tìm thấy.
- echo “Trong:” {}: Đây là lệnh., Chúng tôi chỉ đơn giản là lặp lại tên của thư mục tới cửa sổ đầu cuối. “{}” Giữ tên của thư mục hiện tại.
- U0026quot;: Đây là dấu chấm phẩy dùng để kết thúc lệnh. Chúng ta cần thoát khỏi nó bằng dấu gạch chéo ngược để Bash không diễn giải nó một cách trực tiếp.
Với một chút thay đổi, chúng ta có thể làm cho lệnh find trả về các tệp khớp với một đầu mối tìm kiếm. Chúng tôi cần bao gồm tùy chọn -name và một đầu mối tìm kiếm. Trong ví dụ này, chúng tôi đang tìm kiếm các tệp văn bản khớp với “* .txt” và lặp lại tên của chúng với cửa sổ dòng lệnh.
find work -name "*.txt" -type f -execdir echo "Found:" {} ;
Cho dù bạn tìm kiếm tệp hoặc thư mục phụ thuộc vào những gì bạn muốn đạt được. Để chạy một lệnh bên trong mỗi thư mụcsử dụng -type d
. Để chạy một lệnh trên mỗi tệp phù hợpsử dụng -type f
.
Lệnh này đếm các dòng trong tất cả các tệp văn bản trong thư mục bắt đầu và các thư mục con.
find work -name "*.txt" -type f -execdir wc -l {} ;
CÓ LIÊN QUAN: Cách sử dụng lệnh find trong Linux
Duyệt cây thư mục bằng tập lệnh
Nếu bạn cần duyệt qua các thư mục bên trong một tập lệnh, bạn có thể sử dụng find
lệnh bên trong tập lệnh của bạn. Nếu bạn cần — hoặc chỉ muốn — tự thực hiện các tìm kiếm đệ quy, bạn cũng có thể làm điều đó.
#!/bin/bash shopt -s dotglob nullglob function recursive và}#13; local current_dir dir_or_file for current_dir in $1; do echo "Directory command for:" $current_dir for dir_or_file in "$current_dir"/*; do if [[ -d $dir_or_file ]]; then recursive "$dir_or_file" else wc $dir_or_file fi done done } recursive "$1"
Sao chép văn bản vào một trình chỉnh sửa và lưu nó dưới dạng “recurse.sh”, sau đó sử dụng chmod
lệnh để làm cho nó có thể thực thi được.
chmod +x recurse.sh
Tập lệnh đặt hai tùy chọn trình bao, dotglob
và nullglob
.
Các dotglob
cài đặt có nghĩa là tên tệp và thư mục bắt đầu bằng dấu chấm “.
”Sẽ được trả về khi các cụm từ tìm kiếm theo ký tự đại diện được mở rộng. Điều này có nghĩa là chúng tôi đang bao gồm các tệp và thư mục ẩn trong kết quả tìm kiếm của mình.
Các nullglob
cài đặt có nghĩa là các mẫu tìm kiếm không tìm thấy bất kỳ kết quả nào được coi là một chuỗi trống hoặc rỗng. Họ không mặc định cho chính cụm từ tìm kiếm. Nói cách khác, nếu chúng tôi đang tìm kiếm mọi thứ trong một thư mục bằng cách sử dụng ký tự đại diện dấu hoa thị “*
“, Nhưng không có kết quả, chúng tôi sẽ nhận được một chuỗi rỗng thay vì một chuỗi có chứa dấu hoa thị. Điều này ngăn tập lệnh vô tình cố gắng mở một thư mục có tên “*” hoặc coi “*” là tên tệp.
Tiếp theo, nó định nghĩa một hàm được gọi là recursive
. Đây là nơi những điều thú vị xảy ra.
Hai biến được khai báo, được gọi là current_dir
và dir_or_file
. Đây là các biến cục bộ và chỉ có thể được tham chiếu trong hàm.
Một biến được gọi là $1
cũng được sử dụng trong hàm. Đây là tham số đầu tiên (và duy nhất) được truyền cho hàm khi nó được gọi.
Tập lệnh sử dụng hai for
vòng lặp, một cái lồng vào bên trong cái kia. Đầu tiên (bên ngoài) for
vòng lặp được sử dụng cho hai điều.
Một là chạy bất kỳ lệnh nào bạn muốn thực hiện trong mỗi thư mục. Tất cả những gì chúng ta đang làm ở đây là lặp lại tên của thư mục tới cửa sổ đầu cuối. Tất nhiên, bạn có thể sử dụng bất kỳ lệnh hoặc chuỗi lệnh nào hoặc gọi một hàm script khác.
Điều thứ hai mà vòng lặp for bên ngoài làm là kiểm tra tất cả các đối tượng hệ thống tệp mà nó có thể tìm thấy — đó sẽ là tệp hoặc thư mục. Đây là mục đích của bên trong for
vòng. Đổi lại, mỗi tên tệp hoặc thư mục được chuyển vào dir_or_file
Biến đổi.
Các dir_or_file
sau đó biến được kiểm tra trong một câu lệnh if để xem nó có phải là một thư mục hay không.
- Nếu đúng như vậy, hàm sẽ gọi chính nó và chuyển tên của thư mục làm tham số.
- Nếu
dir_or_file
biến không phải là một thư mục, thì nó phải là một tệp. Bất kỳ lệnh nào bạn muốn áp dụng cho tệp đều có thể được gọi từelse
mệnh đề củaif
bản tường trình. Bạn cũng có thể gọi một hàm khác trong cùng một tập lệnh.
Dòng cuối cùng trong tập lệnh gọi recursive
chức năng và vượt qua trong lần đầu tiên dòng lệnh tham số $1
làm thư mục bắt đầu để tìm kiếm. Đây là thứ bắt đầu toàn bộ quá trình.
Hãy chạy script.
./recurse.sh work
Các thư mục được duyệt qua và điểm trong tập lệnh nơi lệnh sẽ được chạy trong mỗi thư mục được chỉ ra bằng dòng “Lệnh thư mục cho:”. Các tệp được tìm thấy có wc
chạy lệnh trên chúng để đếm dòng, từ và ký tự.
Thư mục đầu tiên được xử lý là “work”, tiếp theo là mỗi nhánh thư mục lồng nhau của cây.
Một điểm thú vị cần lưu ý là bạn có thể thay đổi thứ tự mà các thư mục được xử lý, bằng cách di chuyển các lệnh dành riêng cho thư mục từ phía trên vòng lặp for bên trong sang bên dưới nó.
Hãy chuyển dòng “Lệnh thư mục cho:” sang sau done
của bên trong for
vòng.
#!/bin/bash shopt -s dotglob nullglob function recursive và}#13; local current_dir dir_or_file for current_dir in $1; do for dir_or_file in "$current_dir"/*; do if [[ -d $dir_or_file ]]; then recursive "$dir_or_file" else wc $dir_or_file fi done echo "Directory command for:" $current_dir done } recursive "$1"
Bây giờ chúng ta sẽ chạy script một lần nữa.
./recurse.sh work
Lần này các thư mục có các lệnh được áp dụng cho chúng từ các tầng sâu nhất trước tiên, làm việc sao lưu các nhánh của cây. Thư mục được truyền làm tham số cho tập lệnh được xử lý cuối cùng.
Nếu điều quan trọng là phải xử lý các thư mục sâu hơn trước, thì đây là cách bạn có thể thực hiện.
Đệ quy là kỳ lạ
Nó giống như tự gọi cho chính mình trên điện thoại của bạn và để lại một tin nhắn cho chính bạn để tự nhủ khi gặp bạn lần sau — lặp đi lặp lại.
Có thể mất một chút nỗ lực trước khi bạn nắm bắt được những lợi ích của nó, nhưng khi thực hiện bạn sẽ thấy đó là một cách giải quyết các vấn đề khó theo lập trình một cách thanh lịch.
CÓ LIÊN QUAN: Đệ quy trong lập trình là gì và bạn sử dụng nó như thế nào?
[ad_2]