コマンドが成功した場合は出力をパイプする

コマンドが成功した場合は出力をパイプする
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`

head -1最初のコマンドが成功した場合にのみ、2 番目のコマンド ( ) を実行したいと考えていました。このコマンドを改善するにはどうすればよいですか?

答え1

これを試して:

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`

xargsフラグを渡すと、標準入力 ( ) から少なくとも 1 つの項目を読み取る場合に-rのみ実行されます。basenamehead -1

head -1実行されますが、出力は表示またはキャプチャされません。

また、 からのエラー出力をユーザーに表示したくない場合は、の stderr ストリームを にlsリダイレクトできます。ls/dev/null

INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`

また、 の周囲に引用符を追加したことに注意してください$MY_DIR。こうすることで、スペースが含まれていてもコマンドが失敗しなくなります$MY_DIR

bash などの最新のシェルを使用している場合は、$( )バックティックの代わりにキャプチャ シェルを使用する必要があります。また、変数のスタイルを変更することも検討する必要があります。一般に、スクリプトではすべて大文字の変数名の使用は避けてください。このスタイルは、通常、予約変数と環境変数用に予約されています。

input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)

答え2

パイプラインでは、すべてのコマンドが順番にではなく同時に開始され、実行されます。そのため、出力をどこかに保存する必要があります。

if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
  first_file=$(printf '%s\n' "$ls_output" | head -n 1)
  first_file_name=$(basename -- "$first_file")
fi

ファイル名に改行文字が含まれていないことを前提としていることに注意してください。 を使用するとxargs、空白文字、一重引用符と二重引用符、バックスラッシュでも問題が発生します。 変数を引用符で囲まないと、スペース、タブ、ワイルドカード文字で問題が発生します。 を忘れると、--で始まるファイル名で問題が発生します-

文字に関する制限なしに最も古いファイルのベース名を取得するにはzsh(コマンドの引数のサイズ制限の問題も回避します)、次のようにします。

 first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))

一致するものがない場合、そのコマンドは失敗し、スクリプトは中止されます。次の操作も実行できます。

 first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))

この場合、一致する場合first_file_nameは配列に 1 つの要素が含まれ、一致しない場合は 0 の要素が含まれます。次に、次の操作を実行します。

 if (($#first_file_name)); then
    printf 'Match: %s\n' $first_file_name
 else
    echo >&2 No match
 fi

答え3

ディレクトリ内の最新の変更されたファイルを検索します。

latest() {
  local file path=${1:-.} ext=${2-} latest
  for file in "${path%/}"/*"$ext"; do 
    [[ $file -nt $latest ]] && latest=$file
  done
  [[ $latest ]] && printf '%s\n' "$latest"
}

使用法:latest [directory/path/ [.extension]]

を呼び出す代わりにbasename、パラメータ展開を使用します。

in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}

次の内容を含むディレクトリ内:

foo.xml bar.xml baz.xml newest.xml

base_fn 変数の内容は次のようになります。newest

これを適切に使用してリクエストの目的を達成するには:

check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir" "$check_ext"); then
  base_fn=${in_file##*/} base_fn=${base_fn%.*}
else
  printf '%s\n' "No file found in $check_dir" >&2
fi

編集:質問を再検討したところ、ls問題のコマンドは最古ディレクトリ内のファイル。この同じ関数の名前を に変更してoldest[[ $file -ot $oldest ]] && oldest=$file代わりに を使用することで、同じ効果を得ることができます。混乱をおかけして申し訳ございません。

注目すべき重要な点は、人類はいかなる状況においても絶対に ls の出力を解析してはならないということです。絶対に。

答え4

ここでの最善の選択肢は次の通りだと思います:

ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
      INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
      echo "Error!"
fi

ファイルがない場合、ls の戻りコードは 2 になりますが、ファイルが見つかった場合は 0 になります。

関連情報