Bashのファイル名リストからファイル拡張子を削除する方法

Bashのファイル名リストからファイル拡張子を削除する方法

次のbashスクリプトを使用して生成されたファイルのリストからファイル拡張子を削除しようとしています。

 #!/bin/bash
 file_list=$(find . -type f) #assuming that the files are stored in the same directory
 trimmed_file_list=$(printf '%s\n' "${file_list[@]%.*}")
 printf '%s\n' "${trimmed_file_list[@]}"

この拡張機能は拡張機能をクリーンアップしました。最後リストに項目がありますが、前の項目はありません。

たとえば、次のリストが必要です。

 file1.pdf
 file2.pdf
 file3.png

~になる

 file1
 file2
 file3

しかし、私が得るものは次のとおりです。

 file1.pdf
 file2.pdf
 file3

私はこれをループでやりたくなく、パラメータ拡張を使用したいと思います。ファイルの最後の拡張子だけを削除したいので、切り取りを避けたいです。

パラメータの拡張に関するトピックがかなり多く、bashが改行のfindために窒息する可能性があるようです...よくわかりません。他の既存のトピックが問題を説明している場合、何が起こっているのか完全には理解できません。

関連しているようですが、私の問題を解決できないようなトピック:

答え1

1つのコマンドですべてを行うことができます。

find /path/to -type f -execdir bash -c 'printf "%s\n" "${@%.*}"' bash {} +

答え2

私はあなたが文字列ではなく配列を作成したいと思います。

IFS=$'\n' # split on newline only
set -o noglob # disable the glob part
file_list=($(find . -name '*.*' -type f))

または、bash 4.4+を使用してファイルパスを改行に変更しないでください。

readarray -td '' file_list < <(find . -name '*.*' -type f -print0)

その後、ここで再度配列変数を使用する方が合理的ですが、パラメータ拡張が機能するはずです。

trimmed_file_list=("${file_list[@]%.*}")

コード例では、文字列を生成し、文字列全体の最後のドット文字の後のすべての項目を削除するためにパラメータ拡張を要求します。

答え3

コードに配列が含まれていません。また、ファイル名のリストを文字列に入れます$file_list。文字列の内容は終了し、パラメータ置換はfile3.png文字.png列から削除され、最後のファイル名にファイル名のサフィックスがないファイル名文字列が残ります。

複数の個々のオブジェクト(パス名)を単一の文字列に入れると、自動的に名前にスペース(または文字列が使用する区切り文字)を含むファイルでスクリプトが正しく機能しなくなります。それでも空の出力を分割するので、配列を使用すると役に立ちませんfind


現在のディレクトリのすべてのファイル名または下の一般ファイルの拡張子を削除するには、次の手順を実行します。

find . -type f -name "*.*" -exec sh -c '
    for pathname do
        printf "Would move %s to %s...\n" "$pathname" "${pathname%.*}"
        # mv -i "$pathname" "${pathname%.*}"
    done' sh {} +

名前に1つ以上のドットが含まれている一般的なファイルを見つけます。これらのファイルのパス名は、そのファイルを繰り返す小さなシェルスクリプトでバッチされます。ファイル名の最後の点とそれの後のすべてを削除してファイル名を変更するシェルスクリプトです。実際のコマンドは安全上の理由からmvコメントされています。

このfindコマンドは、内部シェルスクリプトのパス名ジェネレータとして機能し、スペース、改行、およびタブを含むパス名を正しく処理できるようにします。コマンドの出力を変数に保存する必要はありません。

パス名の配列がある場合は、おそらく次のように生成された可能性があります。

shopt -s globstar nullglob
file_list=( **/*.* )  # get pathnames of files with dots in their names

その後、サフィックスなしでパス名を出力できます。

printf '%s\n' "${file_list[@]%.*}"

これがあなたに役立つかもしれません。欲しいなら使用サフィックスのないパス名の場合、上記のコマンドを使用した出力はprintf次のようになります。間違ったやるべきこと(これ以上奇妙なパス名を扱わなくなるでしょう)。したがって、ファイル名のサフィックスを削除するタイミングと方法は、結果として実行したい操作によって異なります。

関連:

関連情報