私のスクリプト:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
そして、ここにエラーがあります:
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
何が間違っているのでしょうか?
答え1
編集前の元のコード:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
チルダ (
~
) は変数のようには動作しません。たとえば、引用符内で使用すると、ホーム ディレクトリへのパスに展開されません。スクリプトでは、$HOME
チルダの代わりに を使用します。は、~
コマンド ラインで使用する「ショートカット」ですが、$HOME
スクリプトではより説明的になります。- 見る "チルダ (~) が二重引用符内で展開されないのはなぜですか?" 詳細については。
cd
ループできるものを何も出力しないので、cd
コマンド置換で を使用するfor
ことは何も役に立ちません。残念ながら、ループで実際に何をしたいのかが不明なので、確実な代替実装を提供することはできません。
編集後のコード:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
このコードは、
"./myscript.sh: 6: cd: can't cd to /test2"
変数名のスペルを間違えた場合_directory1
(スペルを間違えた変数は空で、/test2
ディレクトリは存在しません)。
その後、エラーメッセージを編集しましたまた出力と言うのは
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
これは単にディレクトリが/home/user/test1/test2
存在しないことを意味します。このディレクトリが存在するという証拠は示されていません。する存在するので、システムの言うことを信じるしかありません。
以下は、ディレクトリの内容を一覧表示するスクリプトです (ディレクトリが存在すると仮定)。コードは各ファイルの完全なパス名を出力します。
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
または、
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
shellnullglob
オプションは、指定されたパターンが何にも一致しない場合にループをまったく実行しないようにします。オプションを設定しないとnullglob
、パターンが何にも一致しない場合は展開されず、ループはそれを$name
単一の反復での値として使用します。
隠し名前 (文字で始まるファイル名)に興味がある場合は、dotglob
シェル オプション ( )を設定することもできます。shopt -s dotglob
.
または、各ファイル名のフルパスを印刷せずに、
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
exit 1
が失敗した場合、スクリプトは終了しますcd
。
または、
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
フルパスなしでファイル名のみを印刷するには、以下を使用しますcd
。
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$( basename "$name" )"
# or: printf '%s\n' "${name##*/}"
done
これは、basename
ユーティリティを使用して、パス名のファイル名部分のみを抽出します。コメント内の代替案では、標準のパラメータ置換を使用して、${name##*/}
ファイル名の前の初期ディレクトリ パスを削除します (文字通り、「パターンに一致する最長のプレフィックス文字列*/
を から削除します$name
」)。