-execコマンドオプションとbasenameの検索

-execコマンドオプションとbasenameの検索

次の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

$ img2pdf各画像をPDFファイルに変換するために使用します。これを行うことができる必要があります。

$ find . -type f -name "*.jpg" -exec img2pdf "{}" --output $(basename {} .jpg).pdf \;

結果:

$ 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

.jpgPDFファイル名の一部を削除する方法は?言い換えれば、私はそれを望んCamScanner 01-10-2022 14.54.pdfでいませんCamScanner 01-10-2022 14.54.jpg.pdf

単独で使用すると、$ basename filename .extension拡張子なしでファイル名を印刷します。例:

$ basename CamScanner\ 01-10-2022\ 14.54.jpg .jpg
CamScanner 01-10-2022 14.54

$ findしかし、私のコマンドで構文が機能していないようです。理由をご存知ですか?

注:この部品は同じ部品$ img2pdfと交換しても取り外されません。$ echo$ basename.jpg

$ 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

ベストアンサー1

コマンドの問題findは、周囲のコマンド置換がbasenameシェルによって実行されることです。今後実行も開始されますfindfindパラメータが何であるかを評価するステップとして)。

オプションの引数を持つ単純なユーティリティ以外のものを実行する必要があるたびにfind(たとえば、質問のようにパイプ、リダイレクト、または拡張を実行する必要がある場合)、次のタスクを実行するにはシェルを使用する必要があります。

find . -type f -name '*.jpg' \
    -exec sh -c 'img2pdf --output "$(basename "$1" .jpg).pdf" "$1"' sh {} \;

またはより効率的(各呼び出しはsh -c見つかったパス名のバッチ)

find . -type f -name '*.jpg' -exec sh -c '
    for pathname do
        img2pdf --output "$(basename "$pathname" .jpg).pdf" "$pathname"
    done' sh {} +

またはzsh

for pathname in ./**/*.jpg(.DN); do
    img2pdf --output $pathname:t:r.png $pathname
done

これにより、globbing修飾子を使用して.DN通常のファイルのみを照合し()、非表示.の名前の一致を許可し(D)、一致するものがない場合はパターンを削除します(N)。次に、:t修飾子を使用して「tail」(ファイル名コンポーネント)を抽出$pathnameし、:r結果のデフォルト名(ファイル名サフィックスなし)の「root」を抽出し、それを.png最後に追加します。

上記のすべての変更は次のとおりです。現在のディレクトリに出力を書き込む、JPEGファイルがある場所ならどこでも可能です。すべてのJPEGファイルが現在のディレクトリにある場合、これはまったく必要ではなく、findワイルドカードパターンの拡張に単純なループを使用できます*.jpg

for pathname in ./*.jpg; do
    img2pdf --output "${pathname%.jpg}.png" "$pathname"
done

パラメータ置換は${pathname%.jpg}値の末尾から削除されます。この代替品を使用したい場合があります.jpg$pathname変える basenameJPEGファイルが見つかった元のディレクトリに出力を書きたい場合(findたとえば、次のような複数のディレクトリを使用している場合)

find . -type f -name '*.jpg' -exec sh -c '
    for pathname do
        img2pdf --output "${pathname%.jpg}.pdf" "$pathname"
    done' sh {} +

また見なさい:

おすすめ記事