変数を使用してスクリプト内のディレクトリを変更できない

変数を使用してスクリプト内のディレクトリを変更できない

私のスクリプト:

#!/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
  1. チルダ ( ~) は変数のようには動作しません。たとえば、引用符内で使用すると、ホーム ディレクトリへのパスに展開されません。スクリプトでは、$HOMEチルダの代わりに を使用します。は、~コマンド ラインで使用する「ショートカット」ですが、$HOMEスクリプトではより説明的になります。

  2. 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」)。

関連情報