Как проверить, существует ли файл или каталог файлов в bash?

в настоящее время у меня есть этот скрипт bash (который находится в моем домашнем каталоге, т. е. /home/fusion809/ и я запускаю его как root, поскольку это необходимо для строк копирования значков):

cd /home/fusion809/Pictures/Icon*

declare -a A={Arch,Debian,Fedora,Mageia,Manjaro,OpenSUSE}
declare -a B={Adwaita,Faenza,gnome,Humanity}

for i in $A; do
  for j in $B; do
    if test -e /usr/share/icons/$j/scalable ; else
        mkdir /usr/share/icons/$j/scalable/
    fi
    if test -e /usr/share/icons/$j/scalable/$i.svg ; else
      cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg
    fi
  done
done

что я хочу, чтобы этот скрипт сделал, это скопировать значки из моего до scalable тема (указанному в $B) поддиректориях в /usr/share/icons. Однако, прежде чем он это сделает, я хотел бы создать scalable каталог в этих подкаталогах темы, если он еще не существует. Проблема это то, что другая часть conditionals не читается должным образом, так как я продолжаю получать эту ошибку:

./copyicon.sh: line 8: syntax error near unexpected token `else'
./copyicon.sh: line 8: `    if test -e /usr/share/icons/$j/scalable ; else'

Если вам интересно, почему test -e ... в условном он основан на учебнике по сценариям bash, за которым я следил.

2 ответов


проверка существования файла и/или каталога

чтобы проверить, существует ли файл в Баш, вы используете -f оператора. Для каталогов, используйте -d. Пример использования:

$ mkdir dir
$ [ -d dir ] && echo exists!
exists!
$ rmdir dir
$ [ -d dir ] && echo exists!
$ touch file
$ [ -f file ] || echo "doesn't exist..."
$ rm file
$ [ -f file ] || echo "doesn't exist..."
doesn't exist...

для получения дополнительной информации просто выполнить man test.

Примечание -e этот оператор проверяет, существует ли файл. Хотя это может показаться хорошим выбором, лучше использовать -f который вернет false, если файл не является обычным файлом. /dev/null например, это файл, но не обычный файл. В этом случае возврат проверки true нежелателен.

примечание по переменным

не забудьте также процитировать переменные, как только у вас есть пробел или любой другой специальный символ, содержащийся в переменной, он может иметь нежелательные побочные эффекты. Поэтому, когда вы проверяете наличие файлов и каталогов, оберните файл/dir в двойные кавычки. Что-то вроде [ -f "/path/to/some/${dir}/" ] будет работать, пока следующее не удастся, если есть место в dir: [ -f /path/to/some/${dir}/ ].

исправление синтаксической ошибки

в операторах управления возникает синтаксическая ошибка. Баш if предложение структурировано следующим образом:

if ...; then
    ...
fi

или необязательно с else статья:

if ...; then
    ...
else
    ...
fi

вы не можете пропустить then предложения. Если вы хотите использовать только else предложение вы должны отрицать условие. В результате получается следующий код:

if [ ! -f "/usr/share/icons/$j/scalable" ]; then
    mkdir "/usr/share/icons/$j/scalable/"
fi

здесь мы добавить восклицательный знак (!), чтобы перевернуть оценку выражения. Если выражение имеет значение true, то этому же выражению предшествует ! вернет false и наоборот.


вы не можете пропустить затем часть Если заявление, самым простым решением было бы просто отрицать тест

if [[ ! -e /usr/share/icons/${j}/scalable ]] ; then
    mkdir /usr/share/icons/${j}/scalable/
fi
if [[ ! -e /usr/share/icons/${j}/scalable/${i}.svg ]] ; then
  cp -a ${i}*.svg /usr/share/icons/${j}/scalable/${i}.svg
fi

Я оставил его с-e (существует), но вы можете использовать-d для каталогов или-f для файлов и некоторой обработки ошибок, чтобы поймать материал (например, / usr / share / icons / $j / масштабируемый/ существует, но является файлом, а не каталогом по какой-либо причине.) Я также заметил, что в исходном коде вы потенциально пытаетесь скопировать несколько файлов в один:

cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg

Я оставил его в моем примере в случае, если вы уверены, что это всегда только один файл и намеренно переименовав его. Если нет, я бы предложил только указать целевой каталог.