変数を使用してスクリプト内のディレクトリを変更することはできません。

変数を使用してスクリプト内のディレクトリを変更することはできません。

私のスクリプト:

#!/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コマンド置換で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」)。

関連情報