Bạn có thể sử dụng các mẫu hình cầu nâng cao trong một số shell để khớp với tất cả các tệp trong một thư mục ngoại trừ các mẫu phù hợp với một mẫu cụ thể. Ví dụ: trong ksh, bash hoặc zsh, lệnh
shopt -s extglob ## needed in bash only
setopt ksh_glob ## needed in zsh only
mv /source/!(*.bak) /destination
sẽ di chuyển tất cả các file trong /source
để /destination
trừ các tập tin phù hợp *.bak
. Trong zsh, bạn cũng có thể viết /source/^*.bak
nếu bạn chạy lần đầu tiên setopt extended_glob
và nói chung là (yêu cầu lại setopt extended_glob
) /source/*~*.bak
(hoặc /source/a*~*.bak
cho tất cả các tệp có tên bắt đầu bằng a
ngoại trừ .bak
các tệp, v.v.).
Zsh có một lệnh sao chép / di chuyển / liên kết hàng loạt có thể được sử dụng, trong số những người khác, để di chuyển tất cả các tệp ngoại trừ những tệp phù hợp với một mẫu. Ví dụ: lệnh sau di chuyển tất cả các tệp ngoại trừ *.bak
từ /source
đến target
và thêm .bak
vào tên của chúng trong quy trình:
autoload zmv
zmv '/source/(*)~*.bak' '/target/$1.bak'
Có một số lệnh được gọi là rename
nổi xung quanh. Trên Debian và Ubuntu, /usr/bin/rename
là một tập lệnh perl di chuyển các tệp sang một tên mới được tạo bởi một biểu thức perl. Bạn có thể loại trừ các tệp đổi tên bằng cách không tạo tên mới nếu tệp bị loại trừ. Ví dụ: lệnh sau (sử dụng rename
chương trình cụ thể này ) di chuyển tất cả các tệp ngoại trừ *.bak
từ /source
sang /target
:
rename 's!/source!/target! unless m!\.bak$!' /source/*
Bạn có thể sử dụng find
lệnh để chọn các tệp bạn muốn di chuyển. Ví dụ, lệnh sau sẽ di chuyển tất cả các tệp thông thường ngoại trừ *.bak
trong /source
hoặc thư mục con vào /target
(lưu ý rằng cấu trúc thư mục bị thu gọn):
find /source -type f \! -name '*.bak' -exec mv {} /target/ \;
hoặc (hiệu quả hơn nếu có nhiều tệp để di chuyển)
find /source -type f \! -name '*.bak' -exec sh -c 'mv "$@" "$0"' /target/ {} +
rsync
là một khái quát của cp
và scp
với các quy tắc bao gồm / loại trừ rất mạnh mẽ. Ví dụ: lệnh sau sao chép tất cả các tệp ngoại trừ *.bak
trong /source
hoặc thư mục con vào /target
, tôn trọng cấu trúc thư mục:
rsync -a --exclude '*.bak' /source/ /target/
pax
là (trong số những thứ khác) khác cp
trên steroid. Các quy tắc loại trừ của nó không mạnh bằng rsync, nhưng nó có khả năng bổ sung để đổi tên các tệp khi chúng được sao chép. Nếu bạn đổi tên một tệp thành chuỗi trống, nó sẽ bị loại khỏi bản sao. Ví dụ, lệnh sau sao chép tất cả các tệp ngoại trừ *.bak
trong /source
hoặc thư mục con vào /target
và đổi tên các tệp thành .bak
truyền.
cd /source && pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' . /target/
Ví dụ trên có tác dụng phụ đáng tiếc của việc tạo các thư mục được gọi foo.bak
, có thể tránh được bằng cách kết hợp find
với pax
:
{ cd /source && find . -type f; } | \
pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' /target/
mv file1 file2 /path/to/destination
sẽ không làm những gì bạn muốn