Como mover todos os arquivos dentro das subpastas atuais aqui

8

Também tenho 50 pastas com algumas subpastas, com mais de 1000 arquivos de áudio no total. Preciso remover todas as subpastas e colocar todos os arquivos no nível atual. Tentei, mv */* ./mas reclama: lista de argumentos muito longa

Pedro Gonzalez
fonte

Respostas:

7

Presumo que a extensão dos seus arquivos de áudio seja .mp3

find <AudioFolderPath> -name '*.mp3' -exec mv -it <YourTargetFolder> {} +

Notas:

  • Substitua .mp3pela extensão dos arquivos de áudio

  • Substitua <AudioParentFolderPath>pela pasta pai que contenha suas subpastas.

  • Substitua <YourTargetFolder>pelo caminho da pasta em que você precisa colocar todos os arquivos.

  • Se os arquivos de reboque de diferentes subpastas tiverem o mesmo nome, apenas um será movido.

edit: Como Costas disse: "O -iswitch torna mvinterativo, ele será solicitado antes de substituir os arquivos existentes"

Maomé
fonte
'-t' permite que você especifique o destino primeiro? (como não tenho essa opção no meu "mv" aqui, só posso assumir que, assim, você coloca primeiro a pasta de destino e depois a lista de arquivos a serem movidos para lá ... mas, se não, isso tentará caber a todos no último nome do arquivo, emitindo um aviso) tpoderia ser para "target"?
Olivier Dulac
Sim, como você disse, -tpermita especificar o destino primeiro. a partir da mvpágina de manual: -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY
Muhammad
1
observe que esta é a opção do GNU mv e não está disponível em todos os departamentos (em algum ambiente de produção, pelo menos). Eu fornecer uma solução mais portátil, mas o seu funciona bem para Linux
Olivier Dulac
sim @OlivierDulac, você está certo, obrigado pela sua observação.
Muhammad
4
find . -type f -mindepth 2 -exec mv -t ./ {} +

Observe que esse comando substituirá todos os arquivos com o mesmo nome. Você pode usar isso para ser solicitado antes de substituir:

find . -type f -mindepth 2 -exec mv -it ./ {} +

Explicação

  • -type f : encontre apenas arquivos regulares.
  • -mindepth 2 : encontre apenas arquivos em subdiretórios.
  • -exec mv -it ./ {}: os -execmeios "execute este comando em todos os arquivos encontrados". O {}será substituído pelos nomes dos arquivos. O -iswitch torna mvinterativo, ele será solicitado antes de substituir os arquivos existentes e -tdefinirá o diretório de destino ./.
  • +: reúne arquivos (em uma linha de argumento), tantos quanto o shell pode operar com o comando para invocar o tempo mínimo de comando (não um por um, mas um a vários).

Em relação a exclusões de pastas vazias adicionais, você pode usar a mesma receita:

find . -type d -empty -delete
Costas
fonte
1
-type fseleciona apenas arquivos simples, excluindo links simbólicos, pipes nomeados e similares. Para mover todos os arquivos, exceto os diretórios, você pode fazer ! -type d.
jimmij
@jimmij Suponho que ninguém armazene arquivos de áudio como pipe nomeado ou qualquer outra coisa. Se você se preocupar com links simbólicos você pode usar -Lo parâmetro
Costas
1
-ié padrão, -té GNU-only (nada a ver com Linux, que é apenas um kernel encontrado em alguns sistemas GNU e não-GNU)
Stéphane Chazelas
Concordo com o @ StéphaneChazelas: -tnão existe em alguns sistemas (como um AIX não tão antigo) #
1111 Olivier Dulac
@OlivierDulac É quase impossível encontrar uma decisão para satisfazer a todos, portanto as diferentes variantes são bem-vindas. Ninguém proibi-lo de mudar corda parafind . -type f -mindepth 2 -exec mv {} ./ \;
Costas
2

Sim, esse é um limite para o tamanho cumulativo de argumentos e ambiente passados ​​para a execve()chamada do sistema ao executar um comando externo.

Com zsh, você pode usar seu builtin mv:

zmodload -F zsh/files +b:zf_mv
zf_mv ./*/* .

Ou use zargspara dividir a lista em partes gerenciáveis:

autoload zargs
zargs -Ifiles ./*/* -- mv files .

Com ksh93:

command -x mv ./*/* .

Com o GNU xargse com o GNU mvcom um shell em que printfestá embutido (a maioria, mkshsendo a exceção notável):

printf '%s\0' ./*/* | xargs -r0 mv -t .
Stéphane Chazelas
fonte
Lembre-se de que o OP deseja mover apenas arquivos, não diretórios, portanto, você precisa cuidar disso. Em zshcaso você pode colocar alguns qualificadores glob , por exemplo, (.)ou (^/)após a última *.
jimmij
0

Uma solução bastante portátil pode ser:

encontre todos os arquivos em todas as subpastas e mova-os no diretório atual

find ./*/ -type f -print | xargs mv -i "{}" ./

Você pode adicionar um | egrep "\.au$|\.mp3$|\.ac3$"intermediário para garantir também que os arquivos encontrados sejam arquivos com uma extensão de áudio (adicione quantas extensões forem necessárias para cobrir todo o tipo, apenas forneço três)

Olivier Dulac
fonte
No seu caso, não há necessidade de ligar find. Apenas o suficiente echoouprintf
Costas
@Costas: o OP menciona que existem tantos arquivos que "*" não podem ser expandidos ... Aqui, apenas expiro os nomes de 50 pastas, e o restante é tratado por xargs
Olivier Dulac
Mas findnão resolva o problema, mas resolva xargs.
Costas