rm 組み込みのプロンプト・オプション -i および xargs を使用してユーザーにメッセージを表示して見つけることができません。

rm 組み込みのプロンプト・オプション -i および xargs を使用してユーザーにメッセージを表示して見つけることができません。

使っていますパラメータそしてRMそして探すfind で定義された特定のパターンに従うファイルを削除するには、次の手順を実行します。

touch file
find . -name file | xargs rm

上記のコードはすべてうまくいきますが、rmの-iオプションを入力して次を実行すると:

touch file
find . -name file | xargs rm -i

印刷:

rm:一般的な空のファイル「./file7」を削除しますか?ユーザー@ホスト:$

yまたはnを入力できません。したがって、ファイルは削除されません。

ここで問題は何ですか?

また、xargs -pパラメータが機能することもわかっていますが、より一般的です。すなわち、ユーザに特定のコマンドを実行するように促すメッセージが表示され、これはユーザが操作するのに不便である。

編集:シェルスクリプトでこれを使用したときに私が望むコマンドを実行しましたが、望ましくない find 結果も印刷したことがわかりました。

また、ls file2cmd変数にコマンドを渡すと、file2の仕様は特に印刷されません。と入力すると同じことが起こります rm -i file2。ディレクトリ内のすべてのファイルを削除するように求められます。

これは私のスクリプトです。

#!/bin/bash
touch file{1..9}      # Create 9 files named file1,file2...file9
echo -n 'command: '  # Prompt user
read -e cmd             # read command
find . -exec ${cmd} '{}' +  

私が考えることができる唯一の解決策は、ユーザーに好むモードを選択するように個別にメッセージを表示することです。次に、そのパターンを変数に保存し、パラメータとして渡します。探す堂々とした- 名前オプション。

このような:

#!/bin/bash
touch file{1..9}     # Create 9 files named file1,file2...file9
echo -n 'command: '  # Prompt user for command
read -e cmd          # read command
echo -n 'pattern: '  # Prompt user for pattern
read -e pattern
find . -name "$pattern" -exec ${cmd} '{}' +  

しかし、このソリューションを使用しても探す出力は引き続き印刷され、パターンフィールドが空の場合(つまり、ユーザーがパターンを使用したくない場合)に問題が発生します。

どんなアイデアがありますか?

答え1

xargsはstdinからデータを読み込みます。 rm を使用するとrm -istdin( try ) から応答を読み取ろうとしますtouch test && echo y | r -i test ; ls testが、stdin は xargs によって閉じられるため、(仮定) プロンプトで ctrl-d を押したかのように rm が応答します。

別の解決策はfindの-execオプションです。

touch test
find . -name test -exec rm -i {} \;

答え2

あなたはそれを使用することができますPOSIX -okfindコマンドを続行するかどうかを尋ねるオプションがあります(プロンプトを除いて同じ-exec)。

touch file
find . -name 'file' -ok rm -f {} \;

出力

< rm ... ./file > ? _

答え3

ここでの問題は、(この場合)実行中のコマンドの(標準入力)がstdinリダイレクトされ、ユーザー確認を取得するために使用されるファイル記述子であることです。xargsrm/dev/nullstdinrm

この-aオプションを使用すると、rmは以前にfindコマンドで生成された中間ファイルからファイルのリストを取得できます(この-aオプションを使用するとxargs影響を受けませんstdin)。とにかく中間ファイルが必要なので、これが実際に望むものではないかもしれないことを知っています。以下を使用して、必要なものに似たより直接的な方法を得ることができます。

for i in $(find . -name file); do rm -i "$i"; done

答え4

同様の問題がありましたが、コマンドが出たときに驚きました。

find . -type f -name "*.txt" | xargs rm

このパターンに一致する読み取り専用ファイルが誤って削除されました。

後でマニュアルページで説明を見つけましたrm

ファイルが書き込み可能でなく、標準入力が端末であり、-fまたは--forceオプションが指定されていない場合、または-iまたは--interactive = alwaysオプションが指定されている場合、rmはユーザーにファイルを削除するかどうかを尋ねます。

プロンプトを表示する条件の1つは、標準入力が端末であり、他のコマンドの出力をrm

重要なレッスン:stdinが端末でない場合、rm読み取り専用ファイルは警告なしに削除されます!

find私の場合、書き込み可能なファイルのみを返すようにコマンドを変更することが解決策でした。

find . -type f -writable -name "*.txt" | xargs rm

関連情報