Como encontrar todos os arquivos do tipo e movê-los para um {another_dir} / {dir_files_are_at} / {file}?

0

Eu tenho um monte de diretórios com um monte de arquivos neles e um arquivo de texto. Parece que isso

MainDir
|------dir1
|       |-------file1
|       |-------file2
|       |-------file3.txt
|------dir17
|       |-------file23
|       |-------file34
|       |-------file52.txt
|       |-------file65

O número de arquivos em cada diretório é aleatório e apenas 1 ou nenhum arquivo txt.
Eu preciso mover todos os arquivos txt para "txtFiles" dir dentro de MainDir e cada arquivo txt precisa estar em um subdir com o mesmo nome que o diretório veio (os subdiretórios em txtFiles dir não existem, portanto, precisam ser criados) . É assim que deve parecer linha

MainDir
|------dir1
|       |-------file1
|       |-------file2
|------dir17
|       |-------file23
|       |-------file34
|       |-------file65
|------txtFiles
|       |-------dir1
|       |        |-------file3.txt
|       |-------dir17
|       |        |-------file52.txt

Existe uma maneira de fazer isso com um comando de localização?

Além disso, alguns dos nomes de arquivos e diretórios têm espaços em branco neles

    
por FieryRider 30.09.2017 / 20:16

1 resposta

0
$ tree
.
'-- MainDir
    |-- dir1
    |   |-- notes.txt
    |   |-- some_file-1
    |   |-- some_file-2
    |   '-- some_file-3
    '-- dir17
        |-- README.txt
        |-- some_file-1
        |-- some_file-2
        '-- some_file-3

3 directories, 8 files

Usando rsync :

$ rsync -a --include '*.txt' --exclude '*/*' MainDir/ MainDir/txtFiles/
$ tree
.
'-- MainDir
    |-- dir1
    |   |-- notes.txt
    |   |-- some_file-1
    |   |-- some_file-2
    |   '-- some_file-3
    |-- dir17
    |   |-- README.txt
    |   |-- some_file-1
    |   |-- some_file-2
    |   '-- some_file-3
    '-- txtFiles
        |-- dir1
        |   '-- notes.txt
        '-- dir17
            '-- README.txt

6 directories, 10 files

O comando usa --include '*.txt' para incluir todos os arquivos com .txt nome do arquivo e --exclude '*/*' para excluir outros arquivos. Usando -a ou --archive , uma cópia da parte da hierarquia de origem que é copiada é criada no destino.

Executar isso novamente resultaria em um diretório MainDir/txtFiles/txtFiles vazio sendo criado. Adicionar -m ou --prune-empty-dirs à invocação de rsync evitaria isso.

Usando find (de MainDir ):

$ find . -type f -name '*.txt' ! -path '*/txtFiles/*' \
    -exec sh -c 'for n; do
                     d="txtFiles/${n%/*}";
                     mkdir -p "$d" && cp "$n" "$d"
                 done' sh {} +

Isso localiza todos os arquivos regulares cujos nomes correspondem a *.txt e que não estão em um diretório txtFiles .

Para cada caminho de nome de arquivo encontrado, a parte do diretório do caminho é criada em txtFiles e o arquivo é copiado lá.

A única diferença entre a abordagem rsync e isso é que rsync pode copiar arquivos não regulares que correspondem ao nome dado (diretórios chamados pipes etc.) e que o comando find deve ser executado de dentro de MainDir .

    
por 30.09.2017 / 20:58

Tags