Вопрос: Ls в сценарии bash говорит: «Нет такого файла или каталога»


Ниже приведен скрипт, который я запускаю

#$1 - Argument
declare IPATH="sample/"
declare F=$IPATH$1
echo $F
ls $F

Вход ./script.sh "Fil*"

Выход эха -

sample/Fil*

когда я запускаю команду ls sample/Fil* Я получаю требуемый вывод. Список файлов, имя которых начинается с FIL и находится в папке с образцами, так как это -

sample/File  sample/File1  sample/File2

Но сценарий создает исключение ниже. Что я делаю не так?

ls: sample/Fil*: No such file or directory ls: $IPATH: No such file or directory

2
2018-01-13 11:58


Источник


Здесь происходит что-то очень странное. ls: $IPATH: No such file or directory часть ошибки не имеет никакого смысла - по мере написания сценария ls команда никогда не должна видеть $IPATH, который должен был быть заменен его значением задолго до его приближения ls, Попробуйте добавить set -x в начале включить отслеживание, и посмотреть, что это печатает о том, как он работает. - Gordon Davisson


Ответы:


Globs не расширяются в кавычки, Вы Можно расширьте их в сценариях, но это действительно плохая практика (что, если у кого-то было имя файла, содержащее * или ?? Они не смогут использовать ваш скрипт для манипулирования им). Лучшей практикой является процитировать все ссылки переменных в скриптах и ​​передать фактические пути к скриптам:

$ mkdir sample
$ touch sample/File1 sample/File2
$ cat script.sh 
#!/bin/sh
F="$1"
echo "$F"
ls "$F"
$ ./script.sh sample/Fil*
sample/File1
sample/File1

Или даже лучше, переплюсните все файлы:

$ cat script.sh 
#!/bin/sh
for path
do
    echo "$path"
    ls "$path"
done
$ ./script.sh sample/Fil*
sample/File1
sample/File1
sample/File2
sample/File2

Если вы хотите жестко закодировать часть пути, вы можете использование find расширить его:

while IFS= read -r -d '' -u 9 path
do
    ls -- "$path"
done 9< <( find "sample" -name "$1" -exec printf '%s\0' {} + )

8
2018-01-13 12:40



Я думаю, ЭТО проблема. Но мне нужен характер дикой карты. '». Скажем, я ЗНАЮ, что имена файлов не содержат "». Но я не хочу их расширять и в сценарии. Другого пути нет? - user657592
Более того, я хочу, чтобы часть пути к файлу была жестко закодирована. - user657592
Вы вызываете скрипт с помощью glob, поэтому все, что вам нужно сделать, - это позвонить ему без квотирование глобус. Оболочка позаботится о ее расширении, и пока вы его цитируете внутри сценарий у вас не должно быть проблем. - l0b0


ls выполняется в отдельной оболочке. На этой оболочке IPATH не определяется, так как вы ее не экспортировали.

Измените «declare» на «export», и он будет работать.


-1
2018-01-13 12:01



Я попробовал ваше предложение, но, похоже, это не помогает. - user657592


Возьмите объявлять и он будет работать. Нет необходимости в типирование в Баше:

   #!/bin/sh
   IPATH="sample/"
   F=$IPATH$1
   echo $F
   ls $F

Это будет работать так, как вы ожидаете.


-1
2018-01-13 12:42



Это ничего не меняет AFAICT: ls: cannot access sample/Fil*: No such file or directory, - l0b0
@ l0b0 Потому что это неправильно используется: во-первых, вам не хватает -r / -f / -a ..., тогда вы не можете использовать переменную в выражении $ IPATH $ 1. - MariusMatutiae
Вам не нужно использовать один из этих параметров. Пытаться declare -p | grep 'declare --', IFS, HOSTNAME и другие объявляются без типа, что означает, что они просто строки. - l0b0
@ l0b0: не верно, он отлично работает, просто попробуйте. - MariusMatutiae
@ l0b0 Я запустил код, который вы видели выше, с вызовом ./script.sh "tst *". - MariusMatutiae