Qual linha de comando para percorrer de forma confiável vários níveis de diretório

Qual linha de comando para percorrer de forma confiável vários níveis de diretório

Eu tenho o mesmo problema que foi perguntado na pergunta Renomear arquivos de música com extensões de arquivo ausentes e achei o roteiro fornecido pelo @Gilles muito educativo, mas infelizmente não funcionou como eu esperava. O que eu procurava era um script que adicionasse uma extensão de arquivo a todos os arquivos de música sem extensão em todos os subdiretórios, em todos os níveis, abaixo de "/caminho/para/music/diretório/". O parâmetro de linha de comando sugerido

/path/to/music/directory/{**/,}*

faz com que o script passe por todos os arquivos nos subdiretórios um nível abaixo de "/path/to/music/directory/", mas não em níveis abaixo disso. Qual parâmetro de linha de comando devo usar para percorrer todos os arquivos em todos os níveis abaixo de "directory/" ?

Gostaria também de receber uma indicação da documentação para o

{**/,}* 

papel.

Aliás, para aqueles interessados ​​na resposta original. Descobri que o script funciona melhor depois que mudei a linha

file -i "$@" |

para

file --mime-type "$@" | 

(Se eu tivesse o nível de privilégio, teria dado isso como comentário na resposta original)

Responder1

Acho que você só precisa ativar a globstaropção bash, pois ela não está ativa por padrão noUbuntu, conforme explicado a seguir.

A expressão /path/to/music/directory/{**/,}*contém duas construções de expansão: tem uma expansão de chaves e a seguir uma expansão de nome de caminho.

Expansão de cinta

A expansão do suporte é melhor explicada com um exemplo:

$ printf '%s\n' before-{a,bb,1,22}-after
before-a-after
before-bb-after
before-1-after
before-22-after

(Usei, aqui e a seguir, o comando printf '%s\n' item1 item2 etc..que é parecido echo, mas imprime cada elemento em uma nova linha)

Você vê que cada elemento separado por vírgula entre colchetes resulta em um elemento expandido.

O exemplo original, contendo entre colchetes os elementos **/e um elemento vazio, se expande para

$ printf '%s\n' /path/to/music/directory/{**/,}*
/path/to/music/directory/**/*
/path/to/music/directory/*

estrela glob

Voltemos agora para o bash glob **, que é mencionado duas vezes nopágina de manual do bash, ambos em relação à opção shell globstar, e o significado é o seguinte:

o padrão ** usado em um contexto de expansão de nome de caminho corresponderá a arquivos e zero ou mais diretórios e subdiretórios.

Esta opção de shell não éativopor padrão no Ubuntu:

$ shopt globstar
globstar        off

Você pode ativá-lo com

shopt -s globstar

(use shopt -u globstarpara desativá-lo).

Se tivermos a seguinte estrutura de diretórios:

$ find first/ | sort
first/
first/aaa
first/second
first/second/bbb01
first/second/bbb02
first/second/third
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

poderíamos ter as seguintes expansões:

$ printf '%s\n' first/**/a*
first/aaa

$ printf '%s\n' first/**/b*
first/second/bbb01
first/second/bbb02

$ printf '%s\n' first/**/c*
first/second/third/ccc1
first/second/third/ccc2
first/second/third/ccc3

então você pode ver que **é capaz de expandir para mais de um elemento pathname.

Responder2

eu faria algo assim

#! /bin/bash

[[ -d "$1" ]] || { echo "$1 not a directory, exiting..."; exit 1; }

find "$1" -type f | while read F; do
  # do what you want with the "$F"
done

exit 0

e então invocar o script via./my_script <directory>

informação relacionada