
スクリプトから出力がリダイレクトされました。
$ ls -ltr |awk '{print $9}'
default.txt
dfah.txt
fruit.txt
fruit_prices.txt
dfh.txt
header.txt
testfile.txt
topoutput.txt
シェルに書かれたスクリプト:
while read line
do
var=`sed -e 's/\.txt/txt\.txt/' $line`
echo $var
done < `ls -ltr |awk '{print $9}'`
エラーが発生しました:
-bash: `ls -ltr |awk '{print $9}'`: ambiguous redirect
上記のコードであいまいなリダイレクトがどのように発生するのか、専門家の助けを借りることができますか?
答え1
努力する
ls -ltr |awk '{print $9}' | while read line
do
var=`sed -e 's/\.txt/txt\.txt/' $line`
echo $var
done
このコマンドを発行しました。
while read line ; do
...
done < a b c d
解析できません
答え2
しようとしているようです。
while read line
do
...
done < <(ls -ltr | awk '{print $9}')
しかし、なぜ? while read line
(アケマの答え)がより明確で移植性に優れています。
いいですね。答えをより完全にするには:ZoltánBöszörményiは次のように指摘しています。、
ls -ltr | awk '{print $9}' | while read line
do
...
done
Bash(および他の一部のシェル)では、サブジェクトはサブシェルで実行されるため、シェルのwhile
状態(シェル変数など)の状態の変更はループの外側で持続しません。これについては、次の場所でさらに詳しく説明します。
- Bashで
read
パイプが値を設定しなかった後、 - 私の変数がある
while read
ループではローカルですが、見かけに似た別のループではローカルではないのはなぜですか? - BashFAQ/024: パイプライン内のループに変数を設定しています。ループが終わるとなぜ消えますか?それとも、なぜデータをに転送できないのですか
read
? - そしてここ、 ここ そして ここ スタックオーバーフローに。
< <(…)
この答えの上のコードは問題を回避する1つの方法です。
しかし、もう一つ
あなたはやっていますls -ltr | awk '{print $9}'
。これは、変更された日時順にファイルを一覧表示し、ファイル名を抽出するパッチワークのように見えます。いくつかの質問があります:
- スペースを含むファイル名の場合、この操作は失敗します。
ls
作成しようとすると、自分で追加の作業を行うことです。私情報(ファイルモード、所有者、サイズなど)を一覧表示し、最初に作成する必要がない場合は削除します。
省略すると、両方の問題を解決できます。l
オプション ls
と省略 awk
:
while read line
do
...
done < <(ls -tr)
スペースで始まるか終わるファイル名はまだ問題を引き起こす可能性があります。
また、見ることができますls(1) の出力を分析しない理由。
答え3
"cat file | while read line ..."はサブシェルで "while"の本文を実行するため、シェル変数はサブシェルの外側には表示されませんが、 "while read line ; do ... ; did < <(command ) " を使用して同じシェルで実行します。
これは私のテストファイルです。
$ cat fruits.txt
apple
cherry
pear
plum
両方のスクリプトと結果の違いを見てください。
$ cat a.sh
#!/bin/bash
FOUND=0
while read fruit ; do
case $fruit in
cherry)
echo yay, cherry found
FOUND=1
;;
esac
done < <(cat fruits.txt)
echo cherry found: $FOUND
$ ./a.sh
yay, cherry found
cherry found: 1
しかし、
$ cat b.sh
#!/bin/bash
FOUND=0
cat fruits.txt | while read fruit ; do
case $fruit in
cherry)
echo yay, cherry found
FOUND=1
;;
esac
done
echo cherry found: $FOUND
$ ./b.sh
yay, cherry found
cherry found: 0
答え4
次のようにすることもできます。
while read line; do
var=`echo "$line" |sed -e 's/\.txt/txt\.txt/'`
echo $var
done <<_EOT_
$(ls -ltr | awk '{print $9}')
_EOT_