Я пытаюсь написать чрезвычайно простой script в Ubuntu, который позволил бы мне передать его либо имя файла, либо каталог, и иметь возможность делать что-то конкретное, когда оно является файлом, и что-то еще, когда оно является каталогом, Проблема, с которой я столкнулась, - это когда имя каталога или, возможно, файлы тоже, имеет пробелы или другие эскалатные символы в имени.
Вот мой базовый код ниже, и пара тестов.
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ] ; then
echo "$PASSED is a directory";
else
if [ -f "${PASSED}" ]; then
echo "${PASSED} is a file";
else
echo "${PASSED} is not valid";
exit 1
fi
fi
И вот вывод:
andy@server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory
andy@server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file
andy@server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid
andy@server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid
Все эти пути действительны и существуют.
Это должно сработать. Я не знаю, почему это не удается. Вы правильно цитируете свои переменные. Что произойдет, если вы используете этот script с двойным [[
]]
?
if [[ -d $PASSED ]]; then
echo "$PASSED is a directory"
elif [[ -f $PASSED ]]; then
echo "$PASSED is a file"
else
echo "$PASSED is not valid"
exit 1
fi
Двойные квадратные скобки - это расширение bash до [ ]
. Он не требует цитирования переменных, даже если они содержат пробелы.
Также стоит попробовать: -e
проверить, существует ли путь без проверки того, какой тип файла он имеет.
if [[ ! -f $PASSED ]]
По крайней мере, напишите код без густого дерева:
#!/bin/bash
PASSED=$1
if [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
exit 1
fi
Когда я помещаю это в файл "xx.sh", создаю файл "xx sh" и запускаю его, я получаю:
$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$
Учитывая, что у вас возникли проблемы, вы должны отладить скрипт, добавив:
ls -l "${PASSED}"
Это покажет вам, что ls
думает об именах, которые вы передаете сценарию.
Более элегантное решение
echo "Enter the file name"
read x
if [ -f $x ]
then
echo "This is a regular file"
else
echo "This is a directory"
fi
if [ -f "$x" ]
.
Использование -f
и -d
включает /bin/test
:
F_NAME="${1}"
if test -f "${F_NAME}"
then
echo "${F_NAME} is a file"
elif test -d "${F_NAME}"
then
echo "${F_NAME} is a directory"
else
echo "${F_NAME} is not valid"
fi
test
обычно является встроенной оболочкой, хотя обычно есть исполняемый файл, такой как /bin/test
, а также /bin/[
.)
ОБНОВЛЕНО: Я был заблокирован, поэтому решил переписать свой ответ, спасибо за отзывы.
Использование команды "файл" может быть полезно для этого:
#!/bin/bash
check_file(){
if [ -z "${1}" ] ;then
echo "Please input something"
return;
fi
f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
echo "NO FILE FOUND ($result) ";
elif [[ $result == *"directory"* ]] ;then
echo "DIRECTORY FOUND ($result) ";
else
echo "FILE FOUND ($result) ";
fi
}
check_file ${1}
Примеры вывода:
$ ./f.bash login
DIRECTORY FOUND (login: directory)
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or directory))
$ ./f.bash evil.php
FILE FOUND (evil.php: PHP скрипт, ASCII text)
FYI: ответы выше работают, но вы можете использовать -s, чтобы помочь в странных ситуациях, сначала проверив правильный файл:
#!/bin/bash
check_file(){
local file="${1}"
[[ -s "${file}" ]] || { echo "is not valid"; return; }
[[ -d "${file}" ]] && { echo "is a directory"; return; }
[[ -f "${file}" ]] && { echo "is a file"; return; }
}
check_file ${1}
-s
проверяет непустой файл, файл с ненулевым размером)? И вы не будете печатать какие-либо диагнозы для специальных блоков, специальных символов, FIFO и т.д.? Симлинки, вероятно, разрешают то, что находится в дальнем конце ссылки; сломанные символические ссылки более проблематичны.
Один лайнер
touch bob; test -d bob && echo 'dir' || test -f bob && echo 'file'
результат равен true (0) (dir) или true (0) (файл) или false (1) (ни один)
touch bob
на mkdir bob
, я получу вывод: dir
и file
в две строки.
#!/bin/bash
echo "Please Enter a file name :"
read filename
if test -f $filename
then
echo "this is a file"
else
echo "this is not a file"
fi
if
-else
в Bash также поддерживаютelif
. Просто к вашему сведению.PASSED="$1"