
現在の作業ディレクトリに と の 2 つのフォルダがあるとします。back/
それぞれfront/
のフォルダ内に入って、いくつかの操作を実行しようとしています。以下の簡単なスクリプトから:
for dir in */ ; do
echo "$(dir)"
done
次のような出力を期待していました:
back
front
しかし、私が得ているのは次の通りです:
back front
back front
理解できません。その結果、cd
フォルダにアクセスしようとすると、次のようになります。
for dir in */ ; do
echo "$(dir)"
cd $(dir)
echo "$(pwd)"
cd ..
done
次のような結果になります:
back front
/path/to/back
back front
/path/to/back
つまり、私は決して入力しませんfront/
。誰かが私が何を間違っているのか理解するのを手伝ってくれませんか?
答え1
POSIXのようなシェルでは、$(cmd)
構文は次のようになります。コマンド置換は、末尾の改行文字$(cmd)
を除いた出力に展開されます。cmd
代わりにあなたが望むのはパラメータ拡張:$dir
または${dir}
(ここではパラメータはdir
変数)。
pwd
( p
rint w
orking irectory) は、現在の作業ディレクトリへのパスを含む ¹ 特殊変数d
の内容を出力するコマンドです。したがって、改行文字で終わらない限り、と同じものに展開されます。$PWD
$(pwd)
$PWD
$PWD
あなたが望んでいるのは:
for dir in */; do
(
printf '%s\n' "$dir"
cd -- "$dir" &&
printf '%s\n' "$PWD"
)
done
または:
for dir in */; do
(
printf '%s\n' "$dir"
cd -- "$dir" &&
pwd
)
done
また覚えておいてください
echo
任意のデータを出力するために使用することはできません。printf
代わりに- 通常は、コマンドの終了ステータスを確認する必要があります。ここでの出力を確認しないと、最初のコマンドが失敗した場合に
cd
次のコマンドをcd ..
実行すると間違った場所に行くことになりますcd
。 - を使用するよりも、
cd
サブシェルで実行した方がよいでしょう。後者では必ずしも最初の場所に戻れるとは限らないからです(シンボリックリンクが関係している場合や、パスコンポーネントの一部が区間内で名前変更されている場合)。(...)
cd ..
--
-
非オプションが先頭にないことを保証できない場合(または+
一部のコマンドでは問題になる可能性がある場合)、オプションと非オプションを区別するために使用する必要があります。- POSIX ライクなシェルでは、パラメータ展開とコマンド置換 (および算術展開) は引用符で囲む必要があります。そうしないと、暗黙の split+glob が実行され (zsh を除く)、通常は望ましくありません。
また、bash (および zsh 以外の他の POSIX シェル) では、glob がどのファイルにも一致しない場合は展開されないことに注意してください。
したがって、現在の作業ディレクトリに、隠しファイルでないファイルが含まれていない場合、そのファイルの種類はディレクトリ、 glob パターンは空のリストではなく、*/
それ自体に展開されるため、そのディレクトリに入ることができないというエラーが表示される可能性があります。*/
cd
*/
では、のように glob 修飾子zsh
を使用します(またはで終わるのを避けるために を使用します)。N
for dir in */(N); do...
for dir in *(N-/); do...
$dir
/
ksh93の場合: for dir in ~(N)*/; do...
.
ではbash
、オプションを一時的にグローバルにオンに設定できますnullglob
。
shopt -s nullglob
for dir in */; do
...
done
shopt -u nullglob
$(var)
完全を期すために、大きいMakefile
コマンドで使用される sの展開make
。
言語ではawk
、$
はフィールドを参照解除する単項演算子であり、変数var
を参照するためにのみ使用しますawk
。したがって、はまたは$(var)
と同じになり、番目のフィールド (または が 0 の場合はレコード全体)に展開されます。$var
$ var
var
var
rc
のようなシェルでは、$(var)
と同じように$var
、$ var
、も機能します$ 'var'
。$ ( 'var' )
これは、 に渡される 1 つの要素のリストであるため、通常は のみを使用しますが、変数を$
逆参照しています。var
$var
TCL では、キー$(var)
に空の名前を持つ配列変数の値に展開されますvar
。
$ tclsh
% array set {} {foo 1 bar 2}
% puts $(foo)
1
¹はい、この文脈ではrintP
はP
あまり意味がありません。ご想像のとおり、pwd
コマンド(70年代半ばのUnix V5から)は最初で$PWD
、論理的な現在の作業ディレクトリの処理は、POSIX で規定されているが、後から導入された (80 年代初頭の ksh では、pwd
実際にはprint - $PWD
(引用符-r
と引用符が抜けています!) の別名であり、ドキュメントではresent orking irectory$PWD
という略語で呼ばれていた)。 には、同じ目的で( urrent orking irectory) 変数がある。P
W
D
tcsh
$cwd
c
w
d