Danh sách loại trừ mv dòng lệnh


11

Có cách nào để mv, cphoặc bất kỳ thao tác tệp nào để tôi có thể chỉ định tất cả các tệp tôi không muốn bị ảnh hưởng không?

Ví dụ, nói rằng tôi có một thư mục với các tập tin file1, file2file3, và tôi muốn di chuyển file1file2ở đâu đó. Thay vì đặt tên rõ ràng cho các tệp để di chuyển ( mv file1 file2 /path/to/destination), tôi muốn đặt tên cho các tệp không di chuyển và để tất cả các tệp khác trong thư mục được di chuyển ( mv --some-switch file3 /path/to/destination)


Tôi tin rằng mv file1 file2 /path/to/destinationsẽ không làm những gì bạn muốn
phunehehe

Câu trả lời:


19
  • 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 cpscpvớ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/
    

Tuyệt vời. Một điều chỉnh có thể có: Tôi nghĩ rằng findlệnh cần kết thúc vào\;
Steven D

@Steven: Cảm ơn, tôi tiếp tục quên bạn chỉ có thể sử dụng +ngay sau đây {}.
Gilles 'SO- ngừng trở nên xấu xa'

danh sách tốt đẹp, thx cho điều đó. :-)
echox

1
thật là một câu trả lời, giơ ngón tay cái lên :)
Dzung Nguyen
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.