成功すると、コマンド出力をパイプします。

成功すると、コマンド出力をパイプします。
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`

head -1最初のコマンドが成功した場合にのみ2番目のcommand()を実行したいと思います。このコマンドをどのように改善できますか?

答え1

この試み:

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

xargsこのフラグを渡すと、標準入力()から1つ以上の項目を読み取ったときにのみ実行されます-rbasenamehead -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です。

関連情報