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

Предполагая, что у вас установлен strace:

strace /path/to/binary

изменить :Я не читал последнюю часть, в которой говорилось, что у вас нет strace, вы должны иметь возможность скачать архив strace и собрать его без использования менеджера пакетов. Вы можете создать его статически на другом компьютере и скопировать, если у вас не установлены инструменты сборки.

-2
10.03.2020, 00:36
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» ).

3
28.04.2021, 23:20

Теги

Похожие вопросы