retornando strings correspondentes à correspondência de globos de concha

3

Suponha que eu tenha um subdiretório chamado sub . Então eu quero operar em todos os arquivos nesse diretório com a extensão "txt". Eu quero algo como

for f in sub/*.txt
do
    enscript -b "" -o {$f basename excluding .txt}.ps sub/{$f basename excluding .txt}.txt                                                                                                                             
    ps2pdf {$f basename excluding .txt}.ps {$f basename excluding .txt}.pdf
done

Portanto, se houver apenas um arquivo no diretório sub do formulário *.txt , digamos sub/foo.txt , o script deverá ser expandido para

enscript -b "" -o foo.ps sub/foo.txt                                                                                                                                   
ps2pdf foo.ps foo.pdf

Eu geralmente prefiro soluções portáteis, mas é sempre interessante aprender sobre diferentes maneiras de fazer as coisas. Portanto, não portáteis é Ok, por favor mencione se sua solução é portátil ou não portátil. Além disso, o título provavelmente não é o melhor possível, então sinta-se à vontade para modificar.

EDIT: Eu percebi que o exemplo como escrito não fazia muito sentido, pois foo.txt estava no diretório sub e, portanto, sub/foo.txt precisaria ser passado para enscript . Eu também alterei a opção -p enscript para a opção mais padrão -o .

    
por Faheem Mitha 30.05.2011 / 21:57

2 respostas

4

Cascas POSIX (por exemplo, bash, dash, ksh,…) aceitam uma construção ${var%suffix} que pode ser usado para remover a parte traseira do valor de um variável. Por exemplo, se path="sub/file.txt" , então ${path%.txt} expande para sub/file .

Há uma construção simétrica para remover um prefixo: ${var#prefix} . O prefixo pode ser um padrão. Dobrar o # retira o prefixo correspondente mais longo. Por exemplo, se path=sub/dir/file.txt , então ${path##*/} será expandido para file.txt (e ${path#*/} será expandido para dir/file.txt ). O mesmo vale para sufixos e % .

Então, no seu caso, você poderia escrever isto (note que você não pode combinar o prefixo de decapagem e o sufixo removendo em uma única expansão, pelo menos não apenas com construções POSIX):

for f in sub/*.txt; do
  base=${f%.txt}
  base=${base##*/}
  enscript -b "" -o "$base.ps" "$f"
  ps2pdf "$base.ps" "$base.pdf"
done

Alternativamente, o GNU O comando basename aceita um segundo argumento opcional, que é a extensão de arquivo a ser removida. Para Por exemplo, se $f for file.txt , então $(basename $f .txt) se expandirá para file .

Observe, no entanto, que basename remove todas as informações do caminho, exceto o último componente, então se você quiser remover apenas a extensão você tem que colocar isso de volta (veja o comando dirname ).

    
por 30.05.2011 / 22:09
4

A forma portátil é despir a extensão com ${f%.*} e o diretório com ${f##*/} (ou use basename ) .

Em zsh, você pode aplicar várias transformações a expansão de parâmetros , incluindo modificadores de histórico como r para remover uma extensão e t para remover a parte do diretório.

for x in sub/*.txt; do
    enscript -b "" -o ${x:t:r}.ps $x
    ps2pdf ${x:t:r}.ps ${x:t:r}.pdf
done

Você também pode aplicar modificadores de histórico a padrões de glob .

for x in sub/*.txt(:r:t); do
    enscript -b "" -o $x.ps sub/$x.txt
    ps2pdf $x.ps $x.pdf
done
    
por 30.05.2011 / 22:57