lsの出力をファイルにリダイレクトすると、ファイル名がファイルに含まれます。これをどのように避けることができますか?

lsの出力をファイルにリダイレクトすると、ファイル名がファイルに含まれます。これをどのように避けることができますか?

観察する:

$ ls
$ ls > list
$ cat list
list

lsこれは、ファイルに対してリダイレクトを実行したときにlistすでに起動され、listファイルが作成されたことを示すようです。とにかく、それは十分に良い説明ですが、質問は:どのようにこれが起こらないようにすることができますか?私が期待するのは、lsその出力を実行してダンプすることですがlist、これが私が望むものです。

答え1

ご存知のように、ファイルはls実行前に作成されます。これは、シェルが作業順序を処理する方法によるものです。するために

ls > file

ケーシングが必要作る file次にstdoutがそれを指すように設定し、最後にプログラムを実行しますls

したがって、いくつかのオプションがあります。

  1. 別のディレクトリ(たとえば)にファイルを作成し、/tmp最終mvディレクトリにコピーします。
  2. 隠しファイル()にして.file名前を変更します。
  3. grep出力からファイルを削除するために使用されます。
  4. だまされる:-)

不正行為は次のとおりです。

x=$(ls) ; printf "%s\n" "$x" > file

その結果、出力が変数に保存lsされ、それが作成されます。

答え2

出力ファイルは開始前にシェルによってls生成されます。次の方法を使用してこの問題を解決できますtee

ls | tee list

いかなる競争条件も完全に克服するには、常に

ls | grep -vx 'list' > list

または、必要に応じてtee結果を表示できます。

ls | grep -vx 'list' | tee list

しかし、コメントで指摘したように、ファイル名に奇妙な文字が含まれると、このような問題が発生することがよくあります。 Unixファイル名にはNULand以外の任意の文字を含めることができるため、/出力を解析するのはls非常に困難です。

  • ファイル名が1つ以上\n
  • grepクエリが間にある場合、フィルタリングは失敗します\n
  • NUL代わりに\nファイル名を区別することができますが、findそれを既存のソートされた改行区切り出力のようなものに変換するのは難しいかもしれませんls
  • 出力ファイル名がすでに存在する場合は、リストから削除するのが正しくない可能性があります。

したがって、実際に動作する唯一の方法は、出力ファイルを別の場所に作成してその場所に移動することです。絶対に使用しない場合は、ls -a次のように動作します。

ls > .list && mv .list list

ls -athenを使用すると、.list出力には表示されますが、ディレクトリには存在しなくなる可能性があります。たとえば、/tmp中間結果を保存するために別のディレクトリを使用します。もちろん、常に使用すると問題が発生するため、/tmpスクリプトを書くことができます。

#!/bin/sh
OUTDIR='/tmp'
if [ "${PWD}" = '/tmp' ]; then
  OUTDIR="${HOME}"
fi
ls > "${OUTDIR}/list" && mv "${OUTDIR}/list" list

ただし、これはこれと比較して複雑すぎるようです。

しかし、問題の完全な原因は、コマンドが開始される前にシェルが出力ファイルを生成することです。私たちはこれを考慮して、シェルに私たちのためにファイルをリストさせることができます。もしそうなら、まったく必要ありませんls

printf '%s\n' * > list

これは、ディレクトリに引数リストに収まらないファイルが多すぎるまで機能します。

答え3

あなたはそれを使用することができますmoreutils sponge

ls | sponge list

または以下を使用してzsh

cp =(ls) list

GNUの使用ls:

ls -I list > list

(以前にファイルが呼び出された場合は、そのlistファイルがリストされていないことを意味します。)

出力はとにかくソートされるので、ls次のものを使用することもできます(ファイル名に改行文字が含まれていないと仮定)。

ls | sort -o list

または、二重ソートを避けるためにnsortedをlsサポートしている場合(一部の実装には他のものに対するaがあることに注意してください):-UUls-U

ls -U | sort -o list

答え4

クレジットの一部/ほとんどは@StephenHarrisに渡されます…

echo "`ls`" > list

等しい

echo "$(ls)" > list

関連情報