私のスクリプト:
#!/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
コマンド置換でwithを使用しても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
与えられたパターンが何も一致しない場合、シェルnullglob
オプションによりループはまったく実行されません。このnullglob
オプションが設定されていない場合、ifが何も一致しない場合、パターンは拡張されていないままになり、ループは$name
それを単一の反復でforの値として使用します。
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
」)。