Вопрос:
Я пытаюсь написать чрезвычайно простой 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 проверить, существует ли путь без проверки того, какой тип файла он имеет.
Ответ №1
По крайней мере, напишите код без густого дерева:
#!/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 думает об именах, которые вы передаете сценарию.
Ответ №2
Использование команды “file” может быть полезно для этого:
#!/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 script, ASCII text)
К вашему сведению: приведенные выше ответы работают, но вы можете использовать -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} Ответ №3
Использование -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 Ответ №4
Более элегантное решение
echo «Enter the file name» read x if [ -f $x ] then echo «This is a regular file» else echo «This is a directory» fi Ответ №5
Это должно работать:
#!/bin/bash echo «Enter your Path:» read a if [[ -d $a ]]; then echo «$a is a Dir» elif [[ -f $a ]]; then echo «$a is the File» else echo «Invalid path» fi Ответ №6#!/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 Ответ №7
Один лайнер
touch bob; test -d bob && echo ‘dir’ || (test -f bob && echo ‘file’)
результат равен true (0) (dir) или true (0) (файл) или false (1) (ни один)