Для нахождения любых файлов, которые не содержат определенный шаблон можно использовать:
if ! grep -q $pattern "$file"; then
# The file does not have a match
do_stuff_to "$file"
else
# There is a match
do_something_else_to "$file"
fi
Так, для использования ключевых слов в качестве примера, после Вашего wget
, Вы могли бы использовать:
declare -a KEYWORDS
KEYWORDS=("dolphins" "fish" "dogs" "cats" "iguanas")
for keyword in ${KEYWORDS[@]}; do
for file in **; do
if [[ -r "$file" ]] && ! grep -q $keyword "$file"; do
rm -f "$file"
fi
done
Если Foo важно, то он должен быть настроен в сценарии. Это я думаю, что это хорошая практика, потому что вы тогда явно привязывают это к сценарию. Я не люблю косвенные, неявные или скрытые вещи ... Сценарии должны быть очень просто, если они должны быть развернутыми.
В противном случае, если вы настаиваете на том, чтобы найти его, то его можно найти, делая
whereisfoo="$(which foo)"
, если этого недостаточно, то я боюсь того, что вы можете сделать, слишком сложный.
Вот подход, который я считаю, это чуть менее грязно, чем ответ Gilles (Хотя я уступаю, чтобы быть субъективным суждением).
#!/bin/sh this_dir=$(dirname "$0") # Alternatively, hard-code this as this_dir=$HOME/bin redacted_PATH=$(echo ":${PATH}:" | sed -e "s:\:$this_dir\::\::" -e "s/^://" -e 's/:$//') if obscured_prog=$(PATH=$redacted_PATH which foo) then ⋮ # Munging to do before running /usr/bin/foo "$(obscured_prog)" argument(s) # may be "$@", but might not be. ⋮ # Munging to do after running /usr/bin/foo else echo "$0: foo (real) not found in PATH." ⋮ # Any code that you want to do anyway. fi
Эта конструкция Redacted_Path
Быть $ Путь
Минус $ HOME / BIN
каталог, где эта частная копия Foo
жизни.
ECHO ": $ {путь}:"
добавляет двоеточия до начала и конца $ PATH
,
Таким образом, каждый компонент этого будет предшествовать и сопровождается толстой кишкой -
Даже первый и последний. SED
SED ищет
: $this_dir :
(с пробелами, добавленными для «ясности») и заменяет его с помощью
:
, т. Е. ЭТОТ $ thiss_dir
из »: $ {путь }: «
.
Затем он удаляет двоеточия с самого начала и конца.
Тогда мы временно устанавливаем Путь
на $ Redacted_Path
И искать foo
, используя , который
.
Если успешно, мы получаем полный путь к нему (например, / bin / foo
или / usr / bin / foo
),
Что мы используем для запуска реальной (публичной / общей / системной) копии FOO
.
Так как мы изменили Путь
только временно,
/ bin / foo
имеет доступ к Ambient пользователя $ PATH
,
И так, если / bin / foo
работает BRILLIG
, он может найти $ HOME / BIN / BRILLIG
(если он существует).
У этого возникнет проблема, если $ HOME / BIN
появляется в $ PATH
несколько раз,
Но это не слишком сложно, чтобы исправить.
Не думаю, что есть более простой способ сделать это надежно, чем перечислять каталоги в PATH
. Это не сложно.
#!/bin/bash
set -f; IFS=:
for d in $PATH; do
if [[ -f $d/foo && -x $d/foo && ! $d/foo -ef /home/bob/bin/foo ]]; then
exec "$d/foo" "$@"
exit 126
fi
done
echo "$0: foo (real) not found in PATH"
exit 127
Я полагаю, что в PATH нет пустых записей. Пустые записи PATH - это зло, пишите .
явно (или лучше вообще не включать).
Если вы когда-нибудь будете запускать foo
только из командной строки, а не из других программ, сделайте это функцией, а не сценарием. Из функции выполните команду foo
, чтобы скрыть функцию.
Вы всегда можете получить путь к второму FOO
с:
foo=$(type -Pa foo | tail -n+2 | head -n1)
(предоставленные пути файлов не содержат новых символов).
Остерегайтесь, который может быть относительным путем, который остановится, чтобы быть действительным после запуска CD
.
Вы могли бы сделать:
hash -p "$foo" foo
Так что , что foo
, когда вы запустите foo
.