LINUX.ORG.RU

find .. и отправить весь результат .. а как же пробелы?


0

0

всех приветствую, вопрос вроде как простой, но в течении двухчасовой возни я так и не смог получить то, что нужно, может кто подскажет. Интерпретатор - bash. Вот есть цикл по всем файлам которые ищутся find'ом:

for i in `find $1 -type f | grep -vi .svn` do ..чего-то.. done

классика..казалось бы. Ну так вот, если в имени найденного файла будет пробел, то понятно что имя раздробится и будет фигня. Например, найден файл: /aaa/bbb/cc<пробел>xy параметр i в цикле будет такой: первое значение: /aaa/bbb/cc второе: xy

Как же экранировать пробелы? Или такие вещи как-то по-другому нужно писать? спасибо


например так:

find $1 -type f \
  | grep -vi .svn \
  | while read -r fl; do
      do_smth "$fl"
    done

обрати внимание на кавычки "$fl"

 

dilmah ★★★★★
()

... find . -type f -print0 | xargs -0 grep -vi ...

anonymous
()

>Интерпретатор - bash

Можно на время работы цикла менять значение переменной среды IFS, например перед циклом делать: "OLDIFS="$IFS", IFS=$'\n'", а после цикла восстанавилиать обратно IFS="$OLDIFS". Тогда поля будут разделяться только переводом строки.

Ну, а еще у find есть опция -ls, тогда пробел, перевод строки и прочие символы будут представлены как '\ ', '\n' и т.д.

mky ★★★★★
()

Вообще, стоит почитать какой-нить FAQ по BASH на предмет чтения строк.

Но если конкретнее отвечать на вопрос, то для чтения строк ( из файл например) нужно делать так:

cat file | while read line ; do echo "$line" ; done

// LateARuS

anonymous
()
Ответ на: комментарий от rymis

оооо.... мужики всем громадное спасибо... как же все здорово...

diglan
() автор топика
Ответ на: комментарий от mky

>Можно на время работы цикла менять значение переменной среды IFS, например перед циклом делать: "OLDIFS="$IFS", IFS=$'\n'", а после цикла восстанавилиать обратно IFS="$OLDIFS". Тогда поля будут разделяться только переводом строки.

Гениально! Большое спасибо! Я хоть не автор поста, но мне очень помогло.

Opxocc
()
Ответ на: комментарий от Laz

а -print0 выводит все сплошняяком и тогда вообще не видно отдельный файлов, просто месево получается. О чем и написано в manual..

diglan
() автор топика
Ответ на: комментарий от mky

опция -ls в find не помогает потому что он вметсо пробела ставит posix верный: '\ ' но все равно пробел остается имя дробиться... а вот фокус с $IFS работает! спасибо!

diglan
() автор топика
Ответ на: комментарий от dilmah

dilmah, твой пример один сработал, и я узнал новую функцию read...

спасибо тебе огромное!

diglan
() автор топика

Присоединяюсь к толпе благодарных.

Пример того, "о чём я хотел узнать, но боялся спросить":
(export IFS=$'\n'; ls -l `locate .avi`)

while/xargs запускают новый процесс, что не всегда приятно. Но и за эти примеры тоже большое спасибо!

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

> while/xargs запускают новый процесс

если уж на то пошло, то круглая скобка тоже запускает новый процесс:)

xargs это весьма адекватная штука

> , что не всегда приятно

неприятно когда вместо 2 поцессов запускается 20000. А когда вместо 2 запускается 3 это вполне приемлемо

> (export IFS=$'\n'; ls -l `locate .avi`)

тут ты имеешь проблему если avi файлов слишком много и они превышают лимит на длину командной строки. xargs эту проблему решает

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

Прочитал твоё сообщение, и понял, как сумбурно я выразился :)

Моя исходная (не решённая до прочтения этого треда) проблема - пробелы при ll `locate что-то`.

Вот её решения, которые я тут вычитал, и за которые я благодарю их авторов:

1. (export IFS=$'\n'; ls -l `locate что-то`)

2. locate что-то |while read -r fl; do ls -l "$fl"; done

3. locate что-то |xargs -d \\n -I '{}' ls -l "{}"

Мне проще запомнить первое решение. К тому же оно запускает меньше дочерних процессов. Обычно искомых файлов немного, поэтому переполнение списка аргументов неактуально.

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

да, я понял почему все нормальные люди торчать от юникса:

clear; b=$IFS; IFS=$'\n'; ls -l `find ./ -type f | grep -iv .svn | grep -i scripts`; IFS=$b

это действительно приятно, взять, собрать кучу нужный файлов, например графическихъ, создать на них символьный линки и кинуть все в пасть какого нить просмоторщика типа gthumb.. а в виндухе плодят кучу проиложений, причем понятно, что из математики, чт осистема остается все равно не полной, хоть миллион напиши приложений, пока не замкнешь вход на выход ничего хорошо не выйдет. ха!

diglan
() автор топика
Ответ на: комментарий от alexsaa

> 3. locate что-то |xargs -d \\n -I '{}' ls -l "{}"

> Мне проще запомнить первое решение.

если заменишь на прямолинейное:

locate что-то | tr \\n \\0 | xargs -0 ls -l

то тоже будет легко запомнить.

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

> locate что-то | tr \\n \\0 | xargs -0 ls -l

Круто! Оказывается, xargs ещё умеет группировать элементы в один вызов: в твоём примере ls вызывается один раз (или столько, сколько потребуется, чтобы не переполнялся список аргументов).

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