Xóa đường dẫn khỏi đầu ra lệnh find


29

Tôi có một tập lệnh bash để triển khai mã từ môi trường beta sang môi trường sản xuất nhưng hiện tại tôi phải thêm danh sách các tệp vào tệp txt một cách manaully và đôi khi tôi bỏ lỡ một số. Về cơ bản kịch bản triển khai của tôi cat / vòng lặp sao chép các tập tin trên. (xuất / nhập db là tốt nhưng điều đó không liên quan..lol)

Dù sao, tôi muốn sử dụng findlệnh để tạo danh sách các tệp được sửa đổi trong 14 ngày qua. Vấn đề là tôi cần loại bỏ đường dẫn ./để kịch bản triển khai hoạt động.

Đây là một ví dụ về việc sử dụng lệnh find:

tìm thấy . -type f -mtime -14> triển khai.txt

Đây là dòng mà mèo deploy.txttrong kịch bản triển khai của tôi:

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

Bất kỳ ý tưởng làm thế nào để thực hiện điều này bằng cách sử dụng bash scripting?

Cảm ơn!


3
Có một lý do bạn không thể chỉ sử dụng rsync cho việc này? Nghe có vẻ như bạn có thể đang cố gắng phát minh lại bánh xe và biến nó thành một hình tam giác.
ThatGraemeGuy

tuy nhiên điểm hợp lệ trước khi triển khai triển khai.txt được xem xét và mọi thứ cần sửa chữa đều bị xóa
Mikey1980

1
Có thể chạy rsync trong --dry-runchế độ và xuất ra tệp để xem xét?
Zoredache

Câu trả lời:


36

Bạn có thể sử dụng -printftùy chọn dòng lệnh %fđể chỉ in tên tệp mà không có bất kỳ thông tin thư mục nào

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

hoặc bạn có thể sử dụng sed để loại bỏ ./

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt

Tôi tin rằng bạn phải thoát khỏi /..
EEAA

5
Không phải khi bạn sử dụng |như là dấu phân cách.
user9517 hỗ trợ GoFundMonica

3
Sử dụng %fsẽ loại bỏ tất cả các thư mục, không chỉ ./. Điều này sẽ phá vỡ tập lệnh triển khai của anh ta nếu bất kỳ tệp nào được trả về findnằm trong thư mục con.
James Sneeringer

2
@Iain Bạn cần phải thoát .mặc dù. Và có lẽ tốt nhất để sử dụng mỏ neo bắt đầu:s|^\./||
James O'Gorman

12
Sử dụng %Pthay vì %f. Điều này chỉ cần cắt bỏ đường dẫn được đưa ra trong dòng lệnh.
TrueY

11

Các ./nên vô hại. Hầu hết các chương trình sẽ đối xử /foo/bar/foo/./barnhư là tương đương. Tôi nhận ra nó trông không đẹp lắm, nhưng dựa trên những gì bạn đã đăng, tôi thấy không có lý do gì khiến kịch bản của bạn thất bại.

Nếu bạn thực sự muốn loại bỏ nó, sedcó lẽ là cách sạch nhất:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

Nếu bạn đang ở trên một hệ thống có GNU tìm thấy (ví dụ: hầu hết các hệ thống Linux), bạn có thể thực hiện việc đó trong một lần với find -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

Trả %Pvề đường dẫn đầy đủ của mỗi tệp được tìm thấy, trừ đi đường dẫn được chỉ định trên dòng lệnh, tối đa và bao gồm dấu gạch chéo đầu tiên. Điều này sẽ bảo tồn bất kỳ thư mục con trong cấu trúc thư mục của bạn.


1
Các ./tiền tố thực sự là một tính năng; không có nó, đầu ra đường ống đến các lệnh khác sẽ không hoạt động chính xác, ví dụ như đối với tên tệp bắt đầu bằng dấu gạch ngang.
tripleee

1
@tripleee - Tôi hiểu tiện ích của nó, nhưng OP đặc biệt hỏi làm thế nào để loại bỏ nó vì nó gây ra sự cố cho tập lệnh triển khai của anh ấy. Chắc chắn, có thể có những cách tốt hơn để làm những gì anh ta cần làm, nhưng đó là một lỗ thỏ vượt quá phạm vi của những gì được yêu cầu.
James Sneeringer

7

Tại sao bạn cần phải lột bỏ ./? Đó là một giá trị để có trong một con đường. Vì thế

cp -i dir1/./somefile dir2/./somefile

chỉ là ok

Nhưng nếu bạn muốn loại bỏ tên thư mục trong find Bạn có thể sử dụng %Parg để -printf.

người đàn ông tìm (1) nói:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

Một ví dụ

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

Tâm trí dòng trống đầu tiên! Nếu bạn muốn tránh nó sử dụng-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit

3

Vâng, bạn có một vài lựa chọn. Bạn có thể sử dụng -printftùy chọn tìm kiếm để chỉ in tên tệp hoặc bạn có thể sử dụng một công cụ như sed để chỉ cần loại bỏ ./.

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'

Bạn có thể cho tôi một ví dụ về việc sử dụng nó? Xin lỗi, linux không thực sự là tài sản của tôi
Mikey1980

2
Nhìn lại, có ví dụ.
Zoredache

Đồng ý - chỉ cần thử nó, bạn sẽ không làm tổn thương bất cứ điều gì khi chạy kết hợp tìm và sed.
EEAA

3

Giải pháp "find -printf" sẽ không hoạt động trên FreeBSD vì find không có tùy chọn như vậy. Trong trường hợp này AWK có thể giúp đỡ. Nó trả về một tên cuối cùng ($ NF), vì vậy nó có thể hoạt động ở bất kỳ độ sâu nào.

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS: lấy từ cuốn sách "Lập trình vỏ Linux và Unix" của D.Tansley


2

Một giải pháp nhanh, nếu tôi hiểu chính xác câu hỏi, đang sử dụng cuttrên đầu ra của findlệnh:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

Điều này sẽ loại bỏ các ký tự đầu tiên từ mỗi dòng của kết quả (trong trường hợp của bạn ./). Có lẽ không phải là giải pháp tốt nhất, nhưng hoạt động trong kịch bản của bạn.


1

sed là hoàn hảo cho loại điều này.

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt

1

Tôi không biết chúng ta đang nói về loại tên tập tin nào, nhưng bất cứ điều gì có không gian hoặc dòng mới đều đặt rủi ro cho hầu hết các giải pháp ở đây.

Đề xuất của tôi sẽ là sử dụng mở rộng tham số của shell để tách các ký tự từ mỗi tên tệp:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

Nếu bạn thực sự thích đường ống, bạn có thể sử dụng dấu phân cách "an toàn", như null, với xargs để nhận từng tên tệp:

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

Hãy nhớ rằng đầu ra của cái này KHÔNG được phân tách bằng null, vì vậy trong khi nó có thể đủ để kiểm tra nhãn cầu, không có giải pháp nào trong số này tạo ra tệp triển khai an toàn để sử dụng cho tự động hóa, trừ khi bạn rất tự tin về nguồn của mình tên tập tin.

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.