Como limpar os subdiretórios e recuperar seus nomes no bash?

1

Meus projetos são divididos em três diretórios: dados, scripts e resultados. O pipeline principal é chamado a partir do diretório no topo desses três diretórios. data contém uma série de subdiretórios através dos quais eu quero fazer um loop, recuperar seus nomes e, para preservar a ordem, criar novos diretórios com o mesmo nome em resultados. Eu estou fazendo isso com o seguinte script:

for d in data/*
   do 
   newname=$(echo $d | cut -f2 -d /)
   mkdir /results/$newname
   myprogram $d/raw_data > ../results/$newname/output
   done

que faz o trabalho, mas acho desajeitado ter que cortar o nome do diretório e criar uma variável adicional. Existe uma maneira mais elegante de fazer isso? Uma forma de recuperar o nome do subdiretório em uma única etapa para que eu possa fazer algo como:

for d in (??????)
   do
   mkdir /Results/$d
   myprogram Data/$d/rawdata > results/$d/output
   done

EDITAR Acabei de chegar com esta ideia para a primeira linha, que funciona muito bem com o segundo pedaço de código

for d in $(ls -d  data/* | cut -f2 -d /)

Alguém tem uma sugestão melhor?

    
por je_b 05.09.2016 / 22:36

1 resposta

2

Isso pode ser tratado com a remoção de prefixo:

for d in data/*
do
   mkdir "./results/${d#*/}"
   myprogram "$d/raw_data" > "../results/${d#*/}/output"
done

A construção ${d#*/} é chamada remoção de prefixo . Ele remove tudo até o primeiro / na string $d . Como exemplo:

$ d=data/subdir1
$ echo "${d#*/}"
subdir1

Notas

  1. A menos que você deseje a divisão de palavras e a expansão do nome do caminho, todas as variáveis do shell devem estar entre aspas duplas.

  2. ls foi projetado para produzir uma saída amigável para o usuário. Como um exemplo, um nome de arquivo mostrado por ls deve ser exibido corretamente e não corresponde necessariamente ao nome real do arquivo. O uso de ls em scripts deve ser evitado.

  3. Uma alternativa à remoção do prefixo como mostrado acima é o executável dirname .

Documentação

De man bash :

${parameter#word}
${parameter##word}

Remove matching prefix pattern. The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the # case) or the longest matching pattern (the ## case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.

    
por 05.09.2016 / 23:17

Tags