Tenho os seguintes arquivos JPEG:
$ ls -l
-rw-r--r-- 1 user group 384065 janv. 21 12:10 CamScanner 01-10-2022 14.54.jpg
-rw-r--r-- 1 user group 200892 janv. 10 14:55 CamScanner 01-10-2022 14.55.jpg
-rw-r--r-- 1 user group 283821 janv. 21 12:10 CamScanner 01-10-2022 14.56.jpg
Eu uso $ img2pdf
para transformar cada imagem em um arquivo PDF. Fazer isso :
$ find . -type f -name "*.jpg" -exec img2pdf "{}" --output $(basename {} .jpg).pdf \;
Resultado:
$ ls -l *.pdf
-rw-r--r-- 1 user group 385060 janv. 21 13:06 CamScanner 01-10-2022 14.54.jpg.pdf
-rw-r--r-- 1 user group 201887 janv. 21 13:06 CamScanner 01-10-2022 14.55.jpg.pdf
-rw-r--r-- 1 user group 284816 janv. 21 13:06 CamScanner 01-10-2022 14.56.jpg.pdf
Como posso remover a .jpg
parte dos nomes de arquivos PDF? Ou seja, eu quero CamScanner 01-10-2022 14.54.pdf
e não CamScanner 01-10-2022 14.54.jpg.pdf
.
Usado sozinho, $ basename filename .extension
imprime o nome do arquivo sem a extensão, por exemplo:
$ basename CamScanner\ 01-10-2022\ 14.54.jpg .jpg
CamScanner 01-10-2022 14.54
Mas parece que a sintaxe não funciona no meu $ find
comando. Alguma ideia do porquê?
Obs: se substituir $ img2pdf
por $ echo
é igual, $ basename
não se desfaz da .jpg
peça:
$ find . -type f -name "*.jpg" -exec echo $(basename {} .jpg).pdf \;
./CamScanner 01-10-2022 14.56.jpg.pdf
./CamScanner 01-10-2022 14.55.jpg.pdf
./CamScanner 01-10-2022 14.54.jpg.pdf
O problema com o seu
find
comando é que a substituição do comandobasename
é executada pelo shell antes mesmo de começar a ser executadofind
(como uma etapa na avaliação de quaisfind
devem ser os argumentos).Sempre que você precisar executar algo além de um utilitário simples com argumentos opcionais para um nome de caminho encontrado por
find
, por exemplo, se precisar fazer qualquer tubulação, redirecionamento ou expansão (como em sua pergunta), precisará empregar um shell para fazer isso coisas:Ou, mais eficientemente (cada chamada para
sh -c
lidaria com um lote de nomes de caminho encontrados),Ou, com
zsh
,Isso usa o qualificador globbing
.DN
para corresponder apenas a arquivos regulares (.
), para permitir a correspondência de nomes ocultos (D
) e para remover o padrão se nenhuma correspondência for encontrada (N
). Em seguida, ele usa o:t
modificador para extrair a "cauda" (componente de nome de arquivo) de$pathname
,:r
para extrair a "raiz" (sem sufixo de nome de arquivo) do nome base resultante e, em seguida, adiciona.png
ao final.Observe que todas as variações acima gravariam a saída no diretório atual , independentemente de onde o arquivo JPEG foi encontrado. Se todos os seus arquivos JPEG estiverem no diretório atual, não há absolutamente nenhuma necessidade de usar
find
, e você pode usar um loop simples sobre a expansão do*.jpg
padrão globbing:A substituição do parâmetro
${pathname%.jpg}
remove.jpg
do final o valor de$pathname
. Você pode querer usar essa substituição no lugar debasename
se quiser gravar a saída nos diretórios originais onde os arquivos JPEG foram encontrados, no caso de você usarfind
vários diretórios, por exemplo, algo comoVeja também:
Do ponto de vista pragmático, uma vez que você tenha alcançado o estado que você descreve no final de sua pergunta:
Você tem a opção de usar
rename
para obter os nomes de arquivo finais desejados:O comentário de @Ulrich Schwarz é adequado. Para fechar o círculo, vamos supor que você não tenha nenhum nome de arquivo com aspas ou aspas simples.
Adapte sua
find
sintaxe para simplesmente gerar o nome base sem o .jpg e, em seguida, useawk
talvez, para reconstruir aimg2pdf
sintaxe utilizando as extensões.jpg
e quando apropriado:.pdf
Este
find
comando produzirá o nome de base simples:Agora passe esses nomes de base para
awk
e deixe o awk construir a sintaxe correta paraimg2pdf
:Se essa sintaxe estiver correta, canalize-a para seu shell favorito.