次の方法で生成したファイルのリストからファイル名拡張子を削除しようとしています。 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が”のニューラインの使用…本当にわかりません。既存の別のトピックでこの問題が説明されている場合、何が起こっているのか完全には理解できません。
思われるトピック関連しているが、問題が解決しないようです:
コメント
- タイトルに配列が記載されていますが、コードに配列がありません。
- @Kusalanandaありがとうございます! '質問してから、そのことに気づきました。まだ学習中です:)
- @Kusalananda I '先に進み、問題にさらに厳密に一致するように質問を変更しました。これにより、誤ったGoogle検索がページにヒットするのを防ぐことができます。情報ありがとうございます!
回答
すべてを1つのコマンドで実行できます。
find /path/to -type f -execdir bash -c "printf "%s\n" "${@%.*}"" bash {} +
コメント
- ありがとうございます!実際には、配列のコピーを2つ作成する必要があります。1つはファイル名が変更されたメニュー用で、もう1つはメニューからファイルを呼び出すことができるように元のインデックス値を保持します。しかし、bashがどれだけできるかは本当に驚くべきことです!すべてを1つのコマンドに埋め込む機能は、それでも私を驚かせます。 :D
回答
文字列ではなく配列を作成したいと思います:
IFS=$"\n" # split on newline only set -o noglob # disable the glob part file_list=($(find . -name "*.*" -type f))
またはbash4.4 +を使用し、改行文字を含むファイルパスを壊さない:
readarray -td "" file_list < <(find . -name "*.*" -type f -print0)
次に、パラメータ展開が機能するはずですが、ここでは配列変数を再度使用する方が理にかなっています。
trimmed_file_list=("${file_list[@]%.*}")
コードサンプルでは、文字列を作成しています。次に、パラメータ展開で、文字列全体の最後のドット文字の後のすべてを削除するように要求します。
コメント
- ありがとうございます。午前中に机にぶつかったらすぐにテストします。
- これは、そのディレクトリ内のファイル名に空白文字やグロブ文字が含まれていないことを前提としています。
- @Wildcardは次のようになります。最新の編集で対処しました。
- @Wildcardポインタをありがとう! 'プログラムでこのディレクトリにドロップされるファイルを生成しているので、'問題はないはずです。
回答
コードに配列が含まれていません。また、ファイル名のリストを文字列$file_list
に入れます。文字列の内容はfile3.png
で終わり、パラメータを置き換えると文字列から.png
が削除され、ファイル名の単一の文字列が残ります。最後のファイル名にはファイル名サフィックスがありません。
複数の個別のオブジェクト(パス名)を1つの文字列に入れると、名前にスペース(または文字列が使用する区切り文字)が含まれるファイルに対してスクリプトが正しく機能しなくなります。配列を使用しても、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
コマンドの出力を使用することは、間違ったことです(奇妙なパス名を再び処理しないことに戻ります)。また、ファイル名のサフィックスを削除する方法は、結果をどのように処理するかによって異なります。
関連:
コメント
- ありがとうございます!あなたのbashの習得は非常に明白です!私は'まだ表面をこすっています…お時間を割いていただきありがとうございます:)