Я не могу изменить каталог в скрипте с помощью переменных

Я не могу изменить каталог в скрипте с помощью переменных

Мой сценарий:

#!/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

Опция nullglobоболочки делает так, что цикл вообще не запускается, если заданный шаблон ничему не соответствует. Без установки опции 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»).

Связанный контент