Procura de um diretório por arquivos e resultado de saída para um arquivo de texto

5

Existe algum comando para pesquisar um diretório por arquivos e enviar o resultado para um arquivo com um prefixo antes do nome do arquivo encontrado?

Por exemplo, eu tenho um diretório com esses arquivos:

sound1
sound2
sound3 
…

Em seguida, forneça um comando para pesquisar o diretório e gravar os resultados em um arquivo de texto com um prefixo antes, por exemplo,

media sound1
media sound2
media sound3
…

Pergunta bônus

Existe uma maneira de escrever "media1", "media 2" etc ... em vez de apenas "mídia" em um arquivo de texto existente sem excluir o que havia dentro desse arquivo de texto antes?

media1 sound1
media2 sound2
media3 sound3
…
    
por joblade 29.09.2017 / 11:56

5 respostas

3

Que tal um simples loop for ?

for i in *; do echo media $i >> text_file; done

Explicações

  • * - expande para todos os arquivos no diretório atual
  • echo media $i - imprime “mídia” e o nome de arquivo atualmente processado
  • >> text_file - redireciona a saída de echo para um arquivo chamado text_file acrescentando

Exemplo

$ ls
sound1  sound2  sound3

$ for i in *; do echo media $i >> text_file; done

$ cat text_file 
media sound1
media sound2
media sound3

Pergunta bônus

k=0; for i in *; do ((k++)); echo media$k $i >> text_file; done

Ou para muito muitos arquivos (um pouco mais rápidos):

j=text_file; k=0; for i in *; do if [[ "$i" != "$j" ]]; then ((k++)); echo media$k $i; fi; done > "$j"

Explicações

  • k=0 - defina a variável k e defina como 0
  • ((k++)) - incremento $k em um

Exemplo

$ ls
sound1  sound2  sound3

$ k=0; for i in *; do ((k++)); echo media$k $i >> text_file; done

$ cat text_file 
media1 sound1
media2 sound2
media3 sound3
    
por dessert 29.09.2017 / 12:57
2

Primeiro, imprima a lista de arquivos (uma entrada por linha) em um arquivo ( list_of_files )

ls -1 /location/of/the/directory > list_of_files

Em seguida, adicione um prefixo fixo ( media ) a cada linha

sed -i 's/^/media /' list_of_files

Atualização para a questão bônus

Para adicionar numeração, primeiro imprima a lista de arquivos em um arquivo (digamos list_of_files ) como antes. Em seguida, adicione números de linha antes de cada linha

sed -i '=' list_of_files

A saída ficaria assim

1
sound1
2
sound2
...

Em seguida, corrija as quebras de linha

sed -i '{N;s/\n/ /}' list_of_files

A saída seria agora semelhante a esta

1 sound1
2 sound2
...

Então, finalmente, adicione um prefixo fixo ( media ) a cada linha como antes

sed -i 's/^/media/' list_of_files

A saída final seria

media1 sound1
media2 sound2
...
    
por pomsky 29.09.2017 / 13:05
2

Isso pode ajudar:

find /path/to/sound/files -type f -name "sound[0-9]" -printf 'media %f\n' > file.txt

Informação:

sound[0-9] : procure um arquivo com nomes que tenham sound e termine com um número

-printf 'media %f\n' : formate o nome do arquivo com um prefixo de mídia.

> file.txt : Envie para o arquivo chamado file.txt.

    
por George Udosen 29.09.2017 / 13:12
2

Você pode usar o comando find desta maneira:

find . ! -name 'sound.txt' -type f -exec sh -c 'echo "media $(basename {}) "' \; > sound.txt

Explicação:

  • O primeiro argumento é o caminho para o diretório, no exemplo este é o diretório atual . , mas você pode alterá-lo para /any/desired/path/ .

  • ! -name 'sound.txt' - significa que itens com o nome sound.txt serão omitidos.

  • -type f - significa que apenas os arquivos serão encontrados.

  • -exec <command> \; - instrua o comando find para executar <command> .

  • {} é o argumento de saída do comando inteiro antes de -exec - find . ! -name 'sound.txt' -type f .

  • sh -c 'echo "media $(basename {}) "' é o <command> que será executado:

    • sh -c - executa um comando dentro de /bin/sh shell;
    • 'echo "media $(basename {}) "' - comando a ser executado:
    • echo "<something>" - output <something> para STDOUT ;
    • media - apenas uma string;
    • $(<some command>) - trata o resultado de <some command> como string;
    • basename {} - imprime apenas o nome do arquivo sem seu caminho, onde {} é a variável que contém o nome completo do arquivo gerado por find . ! -name 'sound.txt' -type f
  • Finalmente > redireciona STDOUT;

  • sound.txt é o nome do arquivo onde o STDOUT será redirecionado.

Atualização dos comentários. Dentro dos comentários, há duas sugestões para simplificar o comando acima:

  • O comando inicial:

    find . ! -name 'sound.txt' -type f -exec sh -c 'echo "media $(basename {}) "' \;
    
  • Sugestão de sobremesa:

    find . ! -name 'sound.txt' -type f -exec sh -c 'echo media ${0##*/}' {} \;
    
  • Sugestão da Steeldriver:

    find . ! -name 'sound.txt' -type f -printf 'media %f\n'
    

Exemplo de uso. Vamos supor que temos um diretório com a seguinte estrutura:

$ tree .
.
├── sound
├── sound1
├── sound2
├── sound3
├── sound4
├── sound5
├── sound99
└── soundd

As saídas de cada um dos comandos acima serão idênticas entre si:

$ find . ! -name 'sound.txt' -type f -printf 'media %f\n'
media sound1
media soundd
media sound3
media sound5
media sound2
media sound
media sound99
media sound4

Pergunta bônus. De acordo com a pergunta de bônus , o comando find não é a melhor escolha, mas sua saída pode ser canalizada ( | ) para outro comando ou ciclo. E aqui estão dois casos:

  • O primeiro caso é quando queremos contar apenas os resultados media# :

    find . ! -name 'sound.txt' -type f -printf 'media %f\n' | sort | \
    while read -r i; do \
        count=$((count+1)); \
        echo $i | sed "s/media/media$count/"; \
    done
    

    O exemplo de saída deste comando será:

    $ find . ! -name 'sound.txt' -type f -printf 'media %f\n' | sort | while read -r i; do count=$((count+1)); echo $i | sed "s/media/media$count/"; done
    media1 sound
    media2 sound1
    media3 sound2
    media4 sound3
    media5 sound4
    media6 sound5
    media7 sound99
    media8 soundd
    
  • O outro caso é quando queremos atribuir o número de cada sound# arquivo ao seu prefixo media . E como nas circunstâncias do exemplo temos dois arquivos sem nenhum número dentro de seus nomes ( sound , soundd ), devemos adicionar um número exclusivo a eles, então o prefixo será media/# :

    find . ! -name 'sound.txt' -type f -printf 'media %f\n' | sort | \
    while read -r i; do \
        number=$(echo $i | grep -Eo '[0-9]+'); \
        if [ -z $number ]; then \
            count=$((count+1));
            number="\/$count"; \
        fi; \
        echo $i | sed "s/media/media$number\t/"; \
    done
    

    Ou podemos usar essa sintaxe mais simples:

    find . ! -name 'sound.txt' -type f -printf 'media %f\n' | sort  | \
    while read -r i; do \
        number=$(echo $i | grep -Eo '[0-9]+'); \
        [ -z $number ] && count=$((count+1)) && number="\/$count"; \
        echo $i | sed "s/media/media$number\t/"; 
    done
    

    O exemplo de saída deste comando será:

    $ find . ! -name 'sound.txt' -type f -printf 'media %f\n' | sort | while read -r i; do number=$(echo $i | grep -Eo '[0-9]{1,99}'); [ -z $number ] && count=$((count+1)) && number="\/$count"; echo $i | sed "s/media/media$number\t/"; done
    media/1  sound
    media1   sound1
    media2   sound2
    media3   sound3
    media4   sound4
    media5   sound5
    media99  sound99
    media/2  soundd
    
  • Dicas:

    • Você pode copiar e colar um comando de várias linhas diretamente no terminal.

    • Não se esqueça de > sound.text no final do comando para enviar a saída para um arquivo.

    • Tópico com fio .

por pa4080 29.09.2017 / 12:29
0

Experimente este script:

#!/bin/bash
dir='find /home/username/ -name script_test'
ls $dir  > test.txt
sed -i -e 's/^/media /' test.txt
    
por Beginner 29.09.2017 / 12:20