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để /destinationtrừ các tập tin phù hợp *.bak. Trong zsh, bạn cũng có thể viết /source/^*.baknếu bạn chạy lần đầu tiên setopt extended_globvà nói chung là (yêu cầu lại setopt extended_glob) /source/*~*.bak(hoặc /source/a*~*.bakcho tất cả các tệp có tên bắt đầu bằng angoại trừ .bakcá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ừ *.baktừ /sourceđến targetvà thêm .bakvà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à renamenổi xung quanh. Trên Debian và Ubuntu, /usr/bin/renamelà 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 renamechương trình cụ thể này ) di chuyển tất cả các tệp ngoại trừ *.baktừ /sourcesang /target:
rename 's!/source!/target! unless m!\.bak$!' /source/*
Bạn có thể sử dụng findlệ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ừ *.baktrong /sourcehoặ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/ {} +
rsynclà một khái quát của cpvà scpvớ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ừ *.baktrong /sourcehoặ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/
paxlà (trong số những thứ khác) khác cptrê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ừ *.baktrong /sourcehoặc thư mục con vào /targetvà đổi tên các tệp thành .baktruyề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 findvới pax:
{ cd /source && find . -type f; } | \
pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' /target/
mv file1 file2 /path/to/destinationsẽ không làm những gì bạn muốn