Эксперт someone trying to learn bash, I have been making простой scripts to тест out various commands. Простой In the following рукописный шрифт, I am experimenting with the read command.
#!/bin/bash
read -p "Enter a path to a file: " file_to_copy
cp $file_to_copy /tmp
If the user enters the entire path to в тест file e.g. / home / $USER/test when prompted, the рукописный шрифт executes эксперт expected and makes в copy of "тест" in the/tmp directory. However, if the user enters the shorthand ~/test, терминал returns the ошибка cp: cannot stat '~/test': Не such file or directory. Why is the command cp unable to find an equivalent representation of the file path when entered?
If I independently enter in терминал:
cp ~/test /tmp
the тест file is copied without incident, so it is probably в nuance of переменная assignment that I messed up, but I cannot фигурировал it out.
Thanks.
То, что происходит, - то, что Вы буквально просите окружать для нахождения ~/test
из каталога сценарий в настоящее время находится в. Другими словами, если Вы работаете от /home/$USER
, это будет искать файл test
в названном подкаталоге ~
, не расширение /home/$USER/test
.
То, что можно использовать, bash
оценка встроила, который возьмет любые аргументы и соединит их как одну команду и позволит оболочке выполнить ее. Теперь, оболочка расширится ~
.
xieerqi:
$ ./copyScript.sh
Enter a path to a file: ~/test
Entered /home/xieerqi/test
xieerqi:
$ ls -l /tmp/test
-rw-rw-r-- 1 xieerqi xieerqi 0 Dec 21 01:14 /tmp/test
xieerqi:
$ cat copyScript.sh
#!/bin/bash
read -p "Enter a path to a file: " file_to_copy
file_to_copy=$(eval echo $file_to_copy)
echo "Entered $file_to_copy"
cp "$file_to_copy" /tmp
Я предложил бы, чтобы Вы также использовали кавычки вокруг замены команды $( . . .)
, гарантировать, что файлы с пробелами в них и специальном символе будут правильно получены в file_to_copy
переменная
ДОПОЛНЕНИЕ
Как указано в комментариях, eval
встроенный может быть опасным.
Лично, я использую readlink
управляйте довольно часто в моих сценариях и избегайте использования ~
. И с тех пор в этом сценарии Вы просите ввод данных пользователем так или иначе, почему бы не использовать параметры командной строки? Как так:
xieerqi:
$ ./copyScript.sh testFile.txt
/home/xieerqi/testFile.txt
xieerqi:
$ cat copyScript.sh
#!/bin/bash
FILE="$(readlink -f "$@" )"
echo $FILE
# uncomment for copying
# cp $FILE /tmp
dirname и базовое имя
GNU coreutils обеспечивает две команды, basename
и dirname
. basename
шоу длятся элемент в пути, и dirname
шоу все предшествующее последнему элементу. Можно было использовать bash
внутреннее расширение параметра, чтобы сделать то же, но так как у нас есть эти инструменты - почему бы не использовать их:
xieerqi:
$ ./copyScript.sh
Enter path to file: ~/testFile.txt
File entered is /home/xieerqi/testFile.txt
xieerqi:
$ ./copyScript.sh
Enter path to file: ~/sumFile.txt
File entered is /home/xieerqi/sumFile.txt
ERROR, file doesn't exist
xieerqi:
$ cat copyScript.sh
#!/bin/bash
read -p "Enter path to file: " FILEPATH
DIRPATH="$(dirname "$FILEPATH")"
FILENAME="$(basename "$FILEPATH" )"
if [ "$DIRPATH" == "~" ];then
DIRPATH="$HOME"
fi
FILEPATH="$DIRPATH"/"$FILENAME"
echo "File entered is " "$FILEPATH"
[ -e "$FILEPATH" ] || { echo "ERROR, file doesn't exist"; exit 1;}
Попробуйте эти команды в своем сценарии:
#!/bin/bash
read -p "Enter a path to a file: " file_to_copy
file_to_copy=$(bash -c "echo $file_to_copy")
file_to_copy=${file_to_copy/~\//$HOME\/}
cp "${file_to_copy}" /tmp
Объяснение:
третья строка расширится env
значения переменных если любой подарок.
четвертая строка в вышеупомянутом коде попытается искать ~
в Вашем file_to_copy
переменная, и, если найдено это будет замена $HOME
путь.
И \/
здесь \
символ escape-последовательности обратной косой черты для /
, поскольку мы хотим заменить ~/
$HOME/
.