Как использовать команду find для отображения имен файлов, но не путей?

info_ip=`wget --tries=1 --timeout=10 -qO- http://ipinfo.io/?callback=callback; echo`
IFS=$'\n'
IP_country=( $(awk -F'[:"]' '/ip/ || /country/{ print $5}' <<<"$info_ip") )
ip=${IP_country[0]}
country=${IP_country[1]}
echo $ip
echo $country
2
06.01.2021, 17:16
2 ответа

При использовании нескольких выражений в режиме логического ИЛИ с -oвам необходимо заключить их все в \(... \), иначе всегда учитывается результат последнего выражения; и -printf '%f\n'используется для печати имени файла только с удаленными ведущими каталогами.

find. -type f \( -name '*.pdf' -o -name '*.txt' \) -printf '%f\n'

см.man findв ОПЕРАТОРЫ раздел о( expr ):

OPERATORS
...

( expr )
Force precedence. Since parentheses are special to the shell, you will normally need to quote them.

так что вы можете использовать пробелы \(... \)или'('... ')'(после и перед скобками важны ), чтобы избежать их.

3
18.03.2021, 22:38

Как уже упоминалось, вам нужно сгруппировать ваши -nameтесты в круглых скобках. Эти круглые скобки должны быть экранированы как \(... \)или заключены в кавычки, например. '('... ')', чтобы защитить их от оболочки (, где они в противном случае обозначали бы подоболочку ).

Использование стандарта find, а также упрощение работы с суффиксами имен файлов:

set -- txt pdf ods

for suffix do
    set -- "$@" -o -name "*.$suffix"
    shift
done
shift

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename {} \;

Это сначала устанавливает позиционные параметры в список суффиксов имен файлов, которые мы хотели бы видеть (это также можно взять из командной строки, если это скрипт ), и конструирует ИЛИ -список -nameтестов. Затем это используется в командной строке find.

Затем сама команда findвызывает утилиту basenameдля каждого найденного имени.

В качестве альтернативы мы могли бы вместо этого использовать подстановку параметров, чтобы удалить все, кроме компонента имени файла каждого пути, но для этого мы должны передать пути во встроенный sh -cскрипт:

# [...] as before [...]

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec sh -c '
    for pathname do
        printf "%s\n" "${pathname##*/}"
    done' sh {} +

Я ожидаю, что это будет работать быстрее, чем вариант с использованием basename, по крайней мере, если есть много имен файлов для обработки, хотя с GNU basenameот coreutils вы можете использовать -aили --multiple, например:

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename -a {} +

Это вызовет basenameкак можно меньше раз. Но опять же, если у вас установлен coreutils, у вас вполне может быть и findutils с GNU find, и вы можете использовать -printf '%f\n', чтобы сделать то же самое.

1
18.03.2021, 22:38

Теги

Похожие вопросы