Lista de exclusão de linha de comando mv

10

Existe uma maneira de mv , cp ou qualquer operação de arquivo que eu possa especificar todos os arquivos que eu não quero afetar?

Por exemplo, digamos que eu tenha uma pasta com os arquivos file1 , file2 e file3 , e quero mover file1 e file2 em algum lugar. Em vez de nomear explicitamente os arquivos a serem movidos ( mv file1 file2 /path/to/destination ), quero nomear os arquivos não para mover e ter todos os outros na pasta movidos ( mv --some-switch file3 /path/to/destination )

    
por Glide 14.09.2010 / 20:28

1 resposta

19

  • Você pode usar os padrões avançados de globbing em alguns shells para corresponder a todos os arquivos em um diretório, exceto aqueles que correspondam a um padrão específico. Por exemplo, em ksh, bash ou zsh, o comando

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

    moverá todos os arquivos em /source para /destination , exceto os arquivos que correspondem a *.bak . Em zsh, você também pode escrever /source/^*.bak se primeiro executar setopt extended_glob e, mais geralmente (novamente, exigindo setopt extended_glob ) /source/*~*.bak (ou /source/a*~*.bak para todos os arquivos cujo nome comece com a , exceto .bak de arquivos, etc).

  • Zsh tem um comando de copiar / mover / link em massa que pode ser usado, entre outros, para mover todos os arquivos, exceto aqueles que correspondem a um padrão. Por exemplo, o comando a seguir move todos os arquivos, exceto *.bak de /source para target , e adiciona .bak ao nome deles no processo:

    autoload zmv
    zmv '/source/(*)~*.bak' '/target/$1.bak'
    
  • Existem vários comandos chamados rename flutuando. No Debian e no Ubuntu, /usr/bin/rename é um script perl que move arquivos para um novo nome gerado por uma expressão perl. Você pode excluir arquivos de renomeação, não gerando um novo nome se o arquivo for excluído. Por exemplo, o comando a seguir (usando esse programa rename específico) move todos os arquivos, exceto *.bak de /source para /target :

    rename 's!/source!/target! unless m!\.bak$!' /source/*
    
  • Você pode usar o comando find para selecionar os arquivos que deseja mover. Por exemplo, o comando a seguir move todos os arquivos regulares, exceto *.bak in /source ou um subdiretório para /target (observe que a estrutura de diretórios está recolhida):

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

    ou (mais eficiente se houver muitos arquivos para mover)

    find /source -type f \! -name '*.bak' -exec sh -c 'mv "$@" "$0"' /target/ {} +
    
  • rsync é uma generalização de cp e scp com regras de inclusão / exclusão muito poderosas. Por exemplo, o comando a seguir copia todos os arquivos, exceto *.bak in /source ou um subdiretório em /target , respeitando a estrutura de diretório:

    rsync -a --exclude '*.bak' /source/ /target/
    
  • pax é (entre outras coisas) outro cp em esteróides. Suas regras de exclusão não são tão poderosas quanto as do rsync, mas tem a capacidade adicional de renomear os arquivos à medida que são copiados. Se você renomear um arquivo para a string vazia, ele será excluído da cópia. Por exemplo, o comando a seguir copia todos os arquivos, exceto *.bak in /source ou um subdiretório para /target , e renomeia os arquivos para .bak de passagem.

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

    O exemplo acima tem o infeliz efeito colateral de criar diretórios chamados foo.bak , que podem ser evitados combinando find com pax :

    { cd /source && find . -type f; } | \
    pax -rw -pp -s '/.*\.bak$//' -s '/$/.bak/' /target/
    
por 14.09.2010 / 21:20