script para usar a saída de um comando (ls) e usá-lo em outro comando

4

Eu tenho uma coleção de arquivos pdf que eu gostaria de converter para epub. Eu sei que o comando ebook-convert do Calibre vai fazer o truque (eu devo adicionar). Contudo Eu tenho mais de um arquivo.

Eu gostaria de poder executar um script que executa ls > file , em seguida, algo é executado através do dito arquivo e analisa-o para que cada entrada seja uma variável. Em seguida, usa as variáveis como o arquivo de entrada para ebook-convert ; e de alguma forma tem a variável como o arquivo de saída, mas acrescenta um .epub ao final do nome do arquivo?

    
por alburnett 09.06.2011 / 23:37

3 respostas

9

Vou expandir em resposta do jasonwryan , que explica o que, mas não o como ou o porquê.

Você pode usar a saída de um comando como argumentos para outro comando. Isso é chamado de substituição de comando .

some_text='Hello, world'
uppercased="$(echo "$some_text" | tr a-z A-Z)"
echo "Now, it's $uppercased"

No entanto, $(ls …) é horrível por dois motivos:

  • Não analise a saída de ls . Não foi projetado para ser analisável.
  • "$(some-command)" fornece uma string, que é a saída desse comando. Se você tiver um comando que retorne uma lista de elementos, será necessário analisar essa sequência em elementos individuais. Isso é complicado e não confiável, a menos que você possa encontrar um separador simples. Para nomes de arquivos, você não pode encontrar facilmente um separador, porque os nomes de arquivos na maioria dos unices podem conter todos os caracteres⁰.

Observe que, se você escrever $(some-command) em vez de "$(some-command)" , a saída do comando será dividida em palavras e passará por globbing. Até que você entenda a sentença anterior, sempre coloque aspas duplas em torno das substituições de comandos. Quando você entende, sempre coloque aspas duplas, a menos que você saiba por que não pode colocá-las.

Felizmente, gerar a lista de arquivos que correspondem a um determinado padrão é um recurso integrado ao shell. Chama-se globbing .

echo *.pdf

Para atuar em vários arquivos, você usa um loop.

for x in *.pdf; do …; done

O obstáculo restante é gerar o nome do arquivo de destino. O shell possui alguns comandos simples de manipulação de texto, entre os quais ${foo%SUFFIX} para obter o valor de uma variável com um sufixo removido. (Também há ${foo#PREFIX} .)

for x in *.pdf; do
  ebook-convert "$x" "${x%.pdf}.epub"
done

Observe as aspas duplas em torno das substituições de variáveis. A razão é a mesma das substituições de comandos.

Exceto um caractere nulo, mas a maioria das conchas não consegue lidar com isso.

    
por 10.06.2011 / 02:21
6

Esta pode ser uma abordagem mais simples:

for file in *.pdf; do
    ebook-convert "$file" "${file%.pdf}.epub"
done
exit 0
    
por 09.06.2011 / 23:46
2

Resposta de uma linha com a pequena vantagem de que a conversão é executada em paralelo :

parallel ebook-convert {} {.}.epub ::: *.pdf

Eu me acostumei a não usar loops no shell mais. Eles são todos perfeitamente substituíveis pelo GNU Parallel .

    
por 10.06.2011 / 09:51