LINUX.ORG.RU

Экранирование путей при передаче в find

 , , , ,


1

2

В bash-скрипте для проведения некоторых операций над файлами в каталоге используется конструкция:

find "$path" -type f -exec someprog -flag -- "$param" {} \;
При этом иногда она может приводить к неожиданному результату, например в случаях когда имя каталога или файла в $path начинается с дефиса (-) и find воспринимает $path как -опцию. Возможно ли в таких и подобных случаях как-нибудь принудить find однозначно трактовать $path как путь и избежать возможного простреливания ноги?

во всех современных шеллах find не нужен в 99% случаев
в некоторых можно использовать нечто вроде этого
zargs — *{DIR}/*(.) — someprog

zolden ★★★★★
()
Ответ на: комментарий от zolden

Увы, но бывает нужен. Например, в данном случае в zargs будут переданы аргументы, которые shell развернет по твоей маске. А что будет если их __очень__ много ? Будет ошибка «Argument list too long», а в случае же с find, такого не произойдет :)

joy4eg ★★★★★
()
Ответ на: комментарий от joy4eg

Или точно так же find — ${path} ...

Так?

find -- "${path}" -type f -exec someprog -flag -- "$param" {} \;
Это не работает, здесь find всё равно воспринимает $path как -опцию. Тоже думал о том чтобы делать cd, но искал более изящных вариантов.

h578b1bde ★☆
() автор топика
Ответ на: комментарий от joy4eg

А что будет если их __очень__ много

Обычно zargs как раз в случае «Argument list too long» и помогает, даже десятки тысяч файлов не проблема
За много лет я видел только один выдающийся случай, там он упал с другой экзотической ошибкой на директории с более чем 200К файлов

zolden ★★★★★
()

Возможно ли в таких и подобных случаях как-нибудь принудить find однозначно трактовать $path как путь и избежать возможного простреливания ноги?

Со стороны find нет никакой трактовки - это просто строки. Вот со стороны someprog интерпретация -флагов как раз выключается с помощью --, т.е. если someprog нормально написана, то в вашем примере файлы начинающиеся с минусов файлы и так будут трактоваться как файлы.

Кроме того, find «путь» добавляет «путь» ко всем найденным файлам - если он глобальный, то они гарантированно будут начинаться со слеша.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Ответ на: комментарий от slovazap

4.2

Со стороны find нет никакой трактовки
в вашем примере файлы начинающиеся с минусов файлы и так будут трактоваться как файлы
Кроме того, find «путь» добавляет «путь» ко всем найденным файлам - если он глобальный, то они гарантированно будут начинаться со слеша

Сам-то запускать пробовал? Вместо someprog можешь сделать, например, chmod -v:

# ls
test.sh  -v0
# cat test.sh 
#!/bin/bash
path="$1"
param="$2"
find "$path" -type f -exec chmod -v -- "$param" {} \;
# ./test.sh -v0 644
find: невідомий ключ `-v0'
# ./test.sh . 644
права доступу `./test.sh' змінені на 0644 (rw-r--r--)
права доступу `./-v0/test' залишені як 0644 (rw-r--r--)

h578b1bde ★☆
() автор топика
Ответ на: комментарий от salsa

В мане по find рекомендуют, чтобы путь начинался с «/» или "./".

Примерно на таком варианте и остановился: cd -- "$path" && find "$(pwd)"….

h578b1bde ★☆
() автор топика
Ответ на: комментарий от h578b1bde

Товарищ прав, вот так работает :)

[XXX]/tmp/test/ $mkdir -- -f -lla -foo -bar --ffff
[XXX]/tmp/test/ $for i in *; do touch -- $i/${RANDOM}_file; done
[XXX]/tmp/test/ $tree
.
├── -bar
│   └── 17740_file
├── -f
│   └── 9723_file
├── --ffff
│   └── 20392_file
├── -foo
│   └── 20162_file
└── -lla
    └── 7801_file

5 directories, 5 files
[XXX]/tmp/test/ $for dir in *; do find -- "./${dir}" -exec file {} \;; done
./-bar: directory 
./-bar/17740_file: empty 
./-f: directory 
./-f/9723_file: empty 
./--ffff: directory 
./--ffff/20392_file: empty 
./-foo: directory 
./-foo/20162_file: empty 
./-lla: directory 

joy4eg ★★★★★
()
Ответ на: 4.2 от h578b1bde

А, так вы про аргументы find, а не команды. Тогда разумеется ./

slovazap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.