2013-10-12 3 views
1

Я заметил, что find -execdir не переносится, поэтому я решил найти переносимый способ использовать только find -exec для достижения такого же эффекта. Для этого нужно иметь возможность определить, содержит ли путь к каталогу из '/', найденного в 'find', какие-либо символические ссылки и отказываться от него, если это произойдет. Я написал небольшой скрипт, чтобы определить, содержит ли данный путь символические ссылки, но он всегда возвращает код 1, независимо от того, что я ему даю. Никакая команда, которая печатает что-либо, не срабатывает, за исключением случаев, когда я даю ей не-каталог, и в этом случае срабатывает первая команда printf.Почему этот скрипт не работает?

#!/bin/sh -e 
# If any commands fail, the script should return a nonzero status 
[ -d "$1" ] || printf "%s is not a directory" "$1" && exit 1 # Tests if argument is a directory 
cd "$1" || echo "Could not change directory" && exit 1 # If it is a directory, goes to it 
until [ "$PWD" = '/' ] # Loop until root directory reached 
do 
    cd .. || echo "Could not change directory" && exit 1 # Go to parent directory 
    [ -d "$PWD" ] || printf "%s is not directory" "$PWD" && exit 1 # Check that this is a directory 
done 
echo "Given an okay directory" 
exit 0 
+0

Там не должно быть необходимости проверять, если каталог существует несколько раз –

ответ

1

Для каждой строки условий вы должны заключить сбой в (). Например:

[ -d "$1" ] || (printf "%s is not a directory" "$1" && exit 2) 

Я explaun дальше, что написал @Kevin: Если первое утверждение не удается (в [ -d ]), то второе утверждение выполняется. Поскольку второй успешно (только в редких случаях сбой printf), то выполняется последнее утверждение. В этом формате оператор exit не будет выполняться ТОЛЬКО, если ОБА первые два отказались. Если это не каталог, вы получаете printf и exit. В случае, если это каталог, первый || становится истинным, и bash не утруждает себя тестированию следующего (printf) и переходит к &&, который является выходом, снова. Включение сбоев, поскольку это предотвратит это.

+0

Спасибо. Я в конечном счете исправил сценарий, используя условные выражения, которые более подробные, но (ИМО) яснее. – Demi

+0

Также просто интересно: действительно ли мой сценарий (исправно исправленный) преуспевает в своей цели (предотвращая атаки символической ссылки, гарантируя ошибки скрипта вместо разыменования их). – Demi

+0

Собственно, подумайте об этом, это не так. $ PWD всегда будет каталогом. Вы можете использовать что-то вроде 'if [' ls -ld $ PWD | grep '^ l' | wc -l' == 1], затем echo «это ссылка»; выход 1; fi'. Grep будет соответствовать только строкам, начинающимся с 'l', а wc вернет количество согласованных строк. – micromoses

1

В Баш (в отличие от с-подобных языков) && и || имеют одинаковый приоритет. Это означает, что ваши

command || echo error && exit 1 

высказывания интерпретируются как

{ command || echo error } && exit 1 

С echo, скорее всего, удастся даже если command нет, то первый блок преуспеет и exit оператор будет выполняться.

+0

Echo также может выйти из строя, если его вывод будет перенаправлен где-то он не может писать. – Demi

+1

У меня возникли проблемы с представлением сценария, в котором это могло бы произойти, но я все равно смягчил это утверждение. – Kevin

+0

И все равно ваша ошибка. – Kevin

0

Вы можете проверить, не $1 не каталог с обратным ! -d и использовать if; then для выполнения команд после того, как он вернет true.

#!/bin/sh -e 
# If any commands fail, the script should return a nonzero status 
if [ ! -d "$1" ] 
then 
    printf "%s is not a directory" "$1" 
    exit 1 # Tests if argument is a directory 
fi 
cd "$1" # If it is a directory, goes to it 
until [ "$PWD" = '/' ] # Loop until root directory reached 
do 
    cd .. # Go to parent directory 
done 
echo "Given an okay directory" 
exit 0 
Смежные вопросы