一連の「histogram_0000_0000」フォルダを含む親フォルダがあります。すべてのフォルダで "out.txt"ファイルを検索し、フォルダ内のファイルが見つかるたびにそれを返すbashスクリプトを作成しようとしています(ファイルがすべてのフォルダにあることを確認するため)。私が得たスクリプトは次のとおりです。
#!/bin/bash
joblist='job_list.txt'
njobs=`wc ${joblist} | awk '{print $1}'`
cwd=`pwd`
for ((i=1 ; i <= ${njobs} ; i++ )); do
folder=`awk '(NR=='${i}'){print}' ${joblist}`
echo $folder
cd ${folder}
if [ find -name "out.txt" ]
then
echo out.txt found in $folder
fi
cd ${cwd}
done
しかし、実行するたびにエラーが発生します。
./checkrun.sh: 10行目: [: -name: バイナリ演算子が必要
周りを見回して「[[」と「]]」を使ってみましたが、なぜ運が良いのかわかりません!どんな助けでもいいでしょう。ありがとう、ジャック
答え1
[
...]
文字列または数値式をテストします。コマンドが一致することを確認するには、find
出力(空でない文字列、を使用してテスト-n
)を提供するかどうかをテストする必要があります。
if [[ -n "$(find -name 'out.txt')" ]]
then
echo "out.txt found in $folder"
fi
$(...)
コマンドの出力をキャプチャするために廃止された逆引用符の代わりに最新の構文を使用しています`...`
。
他の提案、
行数を取得する
njobs=
にはwc $ {joblist} | awk '{print $1}'``を簡素化できます。njobs=$(wc -l <"$joblist")
$i
awk
変数として渡されました。folder=$(awk -v i="$i" 'NR==i {print}' "$joblist}")
cd
サブフォルダに移動してから、cd
元の場所に戻らないでください。サブディレクトリを参照するには相対パスを使用し、制限されたcd
コンテキストでサブディレクトリを維持するにはサブシェルを使用します。ここでは最初の方法を使用します。echo "$folder" if [[ -n "$(find "$folder" -name 'out.txt')" ]] then echo "out.txt found in $folder" fi
常に相対パスの場合、パス
$folder
として使用される場所ごとに「./$folder」と呼ばれます。これにより、-
ダッシュ()で始まり、ダッシュ()を一連のオプションとして解釈するコマンドに混乱を招く可能性があります。シェルには
bash
すでに現在の作業ディレクトリの変数があるため、次cwd=`pwd`
のように単純化できます。cwd="$PWD"
使用https://shellcheck.net/コードを確認してください。 (プライベートコードの共有が心配な場合は、ローカルにインストールしてください。)
答え2
#!/bin/bash
joblist='job_list.txt'
njobs=`wc ${joblist} | awk '{print $1}'`
cwd=`pwd`
while IFS= read -r line
do
folder="$line" #`awk '(NR=='${i}'){print}' ${joblist}`
echo $folder
cd ${folder}
if [ -f out.txt ]
then
echo out.txt found in $folder
fi
cd ${cwd}
done < job_list.txt
これが役に立つことを願っています。少し簡単です... line=current-line-from'job_list.txt'
1行ずつ読みますので、ファイルは次のようになります。
folder1
folder2
folder234
私の結果:
france1@macubuntu:/tmp/tmdf$ bash script.sh
folder1
folder2
folder234
out.txt found in folder234
france1@macubuntu:/tmp/tmdf$
私が役立つことを願っています...
答え3
zsh
代わりにこれを使用しますbash
。
#! /bin/zsh -
joblist='job_list.txt'
dirs=( ${(f)"$(<$joblist)"} )
for dir in $dirs; do
first_out=( $dir/**/out.txt(NDY1) )
if (( $#first_out )); then
print -r out.txt found in $dir
fi
done
bash
他のGNUの場合はfind
次のようになります。
#! /bin/bash -
joblist='job_list.txt'
dirs=(); readarray -t dirs < "$joblist"
for dir in "${dirs[@]}"; do
[[ -n $dir ]] || continue
[[ $dir = [/.]* ]] || dir=./$dir
first_out=$(find "$dir" -name out.txt -print -quit)
if [[ -n $first_out ]]; then
printf '%s\n' "out.txt found in $dir"
fi
done
いくつかの注意:
readarray -t lines < file
ファイルの行を配列として保存することも可能ですが、開くことがfile
できない場合は実行すらできず、設定もされませんので、事前に変数を初期化することが重要です。readarray
$dirs
bash
最後に、**/
zshスタイルの再帰ワイルドカード()オプションのサポートが追加されましたglobstar
。しかし、まだシンボリックリンク処理(バージョン間の動作の変更)に関連するいくつかの問題があり、さらに重要なのは、この場合、使用されたリストを並べ替えることなく、for、for、または最初の一致時に停止N
などnullglob
のD
globdotglob
修飾子のサポートを追加しないないということです。Y1
上。find
find "$dir"
で始まると$dir
中断されます-
。オプションfind
の終わりの表示のサポートは実際にはサポートされていますが、で始まる引数はオプションでない場合(たとえば、または)、まだ述語として扱われるため、ここでは役に立ちません。だから絶対値ではなく、まだ始まっていないsを前に付けるのです(だからになります)。 BSDはこの問題の防止をサポートしていますが、GNUはまだサポートしていません。--
-
(
)
!
./
$dir
.
-my-annoying-dir-
./-my-annoying-dir-
find
find -f "$dir"
find
- 少なくとも1つが存在することを確認したい場合は、
out.txt
すべてを見つける必要はありません。最初のゲームで止めることができます。したがって(GNUによる)-quit
(一部のBSDには-exit
これに関する規則があります)。 - zshは
${(f)"$(<file)"}
改行に分割されますが、引用符がない場合は空の要素が削除されます(そうでない場合は、次の$dirs
引用符がない次の要素はその要素を削除します)。空のパスは通常有効なパスではないため、エラーが発生する必要がありますが、接続すると、迷惑なことに/something
有効である可能性のある無関係な絶対パスに変わります。前に来ると./
現在のディレクトリになります。したがって、ここではスキップする方が良いです。したがって[[ -n $dir ]] || continue
、bashバリアントです。