Lista wykluczeń mv z wiersza poleceń

11

Czy istnieje sposób mv, cplub jakakolwiek operacja na plikach takie, że mogę określić wszystkie pliki I nie mają wpływu?

Na przykład, że mam folder z plikami file1, file2i file3, i chcę, aby przenieść file1i file2gdzieś. Zamiast jawnie nadawać nazwy plikom move ( mv file1 file2 /path/to/destination), chcę nadać im nazwy plikom, które mają się nie przenosić, i przenieść wszystkie pozostałe w folderze ( mv --some-switch file3 /path/to/destination)

Poślizg
źródło
Wierzę, że mv file1 file2 /path/to/destinationnie zrobi tego, co chcesz
wymyśl

Odpowiedzi:

19
  • Można użyć zaawansowanych wzorców globowania w niektórych powłokach, aby dopasować wszystkie pliki w katalogu oprócz tych pasujących do określonego wzorca. Na przykład w ksh, bash lub zsh polecenie

    shopt -s extglob   ## needed in bash only
    setopt ksh_glob   ## needed in zsh only
    mv /source/!(*.bak) /destination
    

    przeniesie wszystkie pliki /sourcedo, /destinationz wyjątkiem pasujących plików *.bak. W Zsh możesz także pisać, /source/^*.bakjeśli najpierw uruchomisz setopt extended_glob, a bardziej ogólnie (ponownie wymaga setopt extended_glob) /source/*~*.bak(lub /source/a*~*.bakdla wszystkich plików, których nazwa zaczyna się od aoprócz .bakplików itp.).

  • Zsh ma masowe polecenie kopiuj / przenieś / link, którego można używać między innymi do przenoszenia wszystkich plików oprócz tych pasujących do wzorca. Na przykład następujące polecenie przenosi wszystkie pliki oprócz *.bakod /sourcedo targeti dodaje .bakdo nich swoją nazwę:

    autoload zmv
    zmv '/source/(*)~*.bak' '/target/$1.bak'
    
  • Istnieje kilka poleceń nazywanych renameunoszącymi się wokół. W systemach Debian i Ubuntu /usr/bin/renamejest skryptem perla, który przenosi pliki do nowej nazwy generowanej przez wyrażenie perla. Możesz wykluczyć pliki ze zmiany nazwy, nie generując nowej nazwy, jeśli plik ma zostać wykluczony. Na przykład następujące polecenie (za pomocą tego konkretnego renameprogramu) przenosi wszystkie pliki *.bakz wyjątkiem /sourcedo /target:

    rename 's!/source!/target! unless m!\.bak$!' /source/*
    
  • Możesz użyć findpolecenia, aby wybrać pliki, które chcesz przenieść. Na przykład następujące polecenie przenosi wszystkie zwykłe pliki z wyjątkiem *.bakdo /sourcelub podkatalogu do /target(zwróć uwagę, że struktura katalogów jest zwinięta):

    find /source -type f \! -name '*.bak' -exec mv {} /target/ \;
    

    lub (bardziej wydajny, jeśli istnieje wiele plików do przeniesienia)

    find /source -type f \! -name '*.bak' -exec sh -c 'mv "$@" "$0"' /target/ {} +
    
  • rsyncjest uogólnieniem cpi scpz bardzo potężnymi regułami włączania / wyłączania. Na przykład następujące polecenie kopiuje wszystkie pliki z wyjątkiem *.bakw /sourcelub podkatalogu do /target, z zachowaniem struktury katalogów:

    rsync -a --exclude '*.bak' /source/ /target/
    
  • paxjest (między innymi) inny cpna sterydach. Jego reguły wykluczania nie są tak potężne jak rsync, ale ma dodatkową możliwość zmieniania nazw plików podczas ich kopiowania. Jeśli zmienisz nazwę pliku na pusty ciąg, zostanie on wykluczony z kopii. Na przykład następujące polecenie kopiuje wszystkie pliki oprócz *.bakw /sourcelub podkatalogu /targeti zmienia nazwy plików .bak.

    cd /source && pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' . /target/
    

    Powyższy przykład ma niefortunny efekt uboczny tworzenia nazwanych katalogów foo.bak, których można uniknąć, łącząc się findz pax:

    { cd /source && find . -type f; } | \
    pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' /target/
    
Gilles „SO- przestań być zły”
źródło
Niesamowite. Jedna możliwa korekta: Myślę, że findpolecenie musi się zakończyć\;
Steven D
@Steven: Dzięki, wciąż zapominam, że możesz użyć tylko +natychmiast po {}.
Gilles „SO- przestań być zły”
ładna lista, dzięki za to. :-)
echox
1
co za odpowiedź, wielkie kciuki do góry :)
Dzung Nguyen,