Copiar / colar código de loop

4

Eu sou novo no Linux, então aqui está minha pergunta básica. Eu tenho um diretório com 41 pastas. Eu preciso criar um loop para que o processo entra em cada pasta, copie todos os arquivos e cole tudo em uma pasta específica.

Alguma ideia de como abordar isso? Seria muito clicar sem uma solução de código

Na imagem você pode ver todas as pastas que eu preciso acessar e a pasta de saída onde eu quero colar tudo (zPASTE_EVERYTHING_HERE)

Meu caminho é: /shared/home/data/output

Gostaria de colar tudo em: /shared/home/data/output/zPASTE_EVERYTHING_HERE

    
por GCGM 30.10.2017 / 15:51

2 respostas

5

Supondo que:

  • As pastas a serem copiadas e seus arquivos estão em /home/gcgm/myfolders
  • A pasta de saída é /tmp/output-folder

Se você precisar copiar todos os arquivos para outra pasta, faça o seguinte:

mkdir /tmp/output-folder
cd /home/gcgm/myfolders
cp */* /tmp/output-folder

O significado de */* in the this command cp / destino 'é:

  • Pegue todos os arquivos ( o segundo * ) em todos os diretórios ( o primeiro * ) no diretório atual.
por Yaron 30.10.2017 / 15:56
6

Com base no seu exemplo, seu diretório de destino não contém nenhum dígito, enquanto todos os diretórios de origem o fazem. Então, você pode simplesmente usar (GNU) cp como abaixo no diretório pai, em bash :

shopt -s dotglob  #Enables matching hidden files with glob patterns
shopt -s globstar #Enables recursive traverse of directories
cp -t zPASTE_EVERYTHING_HERE *[[:digit:]]*/**/*
  • cp faz a cópia
  • -t zPASTE_EVERYTHING_HERE define o diretório de destino
  • *[[:digit:]]*/**/* corresponde a diretórios que contêm pelo menos um dígito, os percorre (a qualquer profundidade também) e obtém tudo.

Fazendo tudo em um subshell para manter o shell pai intacto; do diretório pai:

( shopt -s dotglob && shopt -s globstar && \
    cp -t zPASTE_EVERYTHING_HERE *[[:digit:]]*/**/* )

Agora, para qualquer nome de diretório de destino aleatório, defina o diretório como GLOBIGNORE variable:

GLOBIGNORE=whatever_destination

Agora, você pode simplesmente fazer:

cp -t whatever_destination */**/*

ou você pode aproveitar extglob :

shopt -s extglob #Should be already set on any interactive shell session
cp -t whatever_destination !(whatever_destination)/**/*

Nota adicional:

Existe uma chance de ARG_MAX ser acionado se você tiver muitos arquivos / diretórios dentro dos diretórios de origem, nesse caso você tem duas opções:

  • Use uma construção for para iterar os arquivos um por um, isso seria muito lento, como você pode imaginar:

    for f in !(whatever_destination)/**/*; do cp -- "$f" whatever_destination/; done
    
  • Use find :

    find . -mindepth 1 -maxdepth 1 -type d -not -name whatever_destination \
        -name '*' -exec sh -c 'cp -rt whatever_destination ""/*' _ {} \;
    
por heemayl 30.10.2017 / 16:05