The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (Shell скрипты)
Изначальное сообщение [ Отслеживать ]

"Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от Af. on 20-Апр-11, 20:13 
Есть шаблон имени  файла с пробелом и парой звёздочек: "/tmp/aaa bbb/*/*"
Как в шелл скрипте получить из этого шаблона список актуально существующих файлов?

Т.е. примерно вот это:


#!/bin/bash

mkdir -p "/tmp/aaa bbb/222"
touch "/tmp/aaa bbb/222/example.txt"
touch "/tmp/aaa bbb/example.txt"

files_to_tar="/tmp/aaa bbb/*/*"

ls "${files_to_tar}"
tar zcpvh -f "/tmp/tar.tar" --directory "/" "${files_to_tar}"

Если в этом примере в последних двух строках стоят кавычки, то "некому" развернуть шаблон - ошибка выходит.
Если кавычки убрать, то пробел в шаблоне мешает.

Можно заменять пробел на '\ ' через "sed 's/ /\\\ /g'" или изменять IFS


IFS_old=$IFS ; IFS=
echo ${files_to_tar}
IFS=$IFS_old

Но дальше не пойму как развернуть две звёздочки... Чтобы в списке были сразу все три файла.

Как оптимальнее сделать?

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от Af. on 20-Апр-11, 20:14 
Простите, патч:

mkdir -p "/tmp/aaa bbb/111"
mkdir -p "/tmp/aaa bbb/222"
touch "/tmp/aaa bbb/111/example.txt"
touch "/tmp/aaa bbb/222/example.txt"
touch "/tmp/aaa bbb/example.txt"

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от LSTemp (ok) on 20-Апр-11, 20:38 
> Простите, патч:
>
 
> mkdir -p "/tmp/aaa bbb/111"
> mkdir -p "/tmp/aaa bbb/222"
> touch "/tmp/aaa bbb/111/example.txt"
> touch "/tmp/aaa bbb/222/example.txt"
> touch "/tmp/aaa bbb/example.txt"
>

[root@local 111]# cat t
#!/bin/bash
find tst -type f
echo "-------------------"
find tst -type f -printf '%f\n'

[root@local 111]# ./t
tst/aaa bbb/111/example.txt
tst/aaa bbb/example.txt
tst/aaa bbb/222/example.txt
-------------------
example.txt
example.txt
example.txt
[root@local 111]#  

или

ls|grep[\|{awk|sed}] юзать в зависимости от потребностей.

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от Af. on 20-Апр-11, 21:22 
> find tst -type f

Да. Но find смотрит либо по всей файловой системе, что часто долго. ls и прочие срабатывают гораздо быстрее. Либо, может быть, надо делать свою обвязку которая будет разбирать шаблон, чтобы установить для find нужные min и max глубину.

Использование "find ... -name ..." приводит к тем же вопросам о пробеле в имени и кавычках, что и для ls, echo и т.п.

P.S. Про обе звёздочки я выше неправильное написал. В конкретном примере никогда мой шаблон не развернётся как три файла, т.к. в шаблоне чётко задаётся глубина в дереве каталогов, а "верхний" файл лежит в каталоге "другой глубины".

Тогда, вероятно, неплохой способ это как-то так:


tar_cmd="tar zcpvh -f \"/tmp/tar.tar\" --directory \"/\" "
IFS_old=$IFS ; IFS=
for val in ${files_to_tar} ; do
    tar_cmd="${tar_cmd} \"${val}\""
done
ls -1 ${files_to_tar}
IFS=$IFS_old

/bin/bash -c "${tar_cmd}"


Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

4. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от LSTemp (ok) on 20-Апр-11, 23:22 
>> find tst -type f
> Да. Но find смотрит либо по всей файловой системе, что часто долго.

...
find [-H] [-L] [-P] [path...] [expression]
...
If  no paths are given, the current directory is used.
...

сырцы конечно не смотрел, но на нах ему path по Вашему? чтобы от корня искать что ли?

> ls и прочие срабатывают гораздо быстрее. Либо, может быть, надо делать

ls несомненно быстрее, но ограничен по возможностям выбора файлов относительно find (собственно поэтому и быстрее).

> свою обвязку которая будет разбирать шаблон, чтобы установить для find нужные
> min и max глубину.

дык установка min max глубины поиска - это святое для find если они заранее известны.
только не понятно зачем нужна специальная обвязка для определения глубины поиска - это бред.

> Использование "find ... -name ..." приводит к тем же вопросам о пробеле
> в имени и кавычках, что и для ls, echo и т.п.

не совсем понимаю о каких проблемах Вы говорите. Что - экранирование символов не работает? Тем более что можно не пользовать name find-a, а grep-у его вывод отдать ...

можно пример задачи?

> P.S. Про обе звёздочки я выше неправильное написал. В конкретном примере никогда
> мой шаблон не развернётся как три файла, т.к. в шаблоне чётко
> задаётся глубина в дереве каталогов, а "верхний" файл лежит в каталоге
> "другой глубины".

а вот теперь я понял кажется задачу - надо вывести файлы ТОЛЬКО из каталога той глубины, что задана маской со звездочками. теперь понятно про глубину поиска..

[root@local eth1]# echo 'zz/qq/*/*/*'|awk '{ gsub(/[^*]/, ""); printf("%s\n", $0) }'|wc -m    
4

[root@local eth1]# echo 'zz/qq/*/*/*'|sed s/[^*]//g|wc -c
4

[root@local eth1]# echo "123"|wc -c  
4

не совсем понятно почему всегда 4, хотя по идее должно быть 3... м/б wc перевод строки считает..

ну тогда как-то так:

[root@local 111]# cat ./t
#!/bin/bash
m='tst/*/*/*'
echo "mask=$m"
p=`echo "$m"|sed 's/\/\*//g'`
echo "path=$p"
d=`echo "$m"|sed s/[^*]//g|wc -c`
d=$(($d-1))
echo "depth=$d"
find tst -mindepth $d -maxdepth $d -type f

[root@local 111]# ./t
mask=tst/*/*/*
path=tst
depth=3
tst/aaa bbb/111/example1.txt
tst/aaa bbb/222/example2.txt
[root@local 111]#  


>[оверквотинг удален]
>

 
> tar_cmd="tar zcpvh -f \"/tmp/tar.tar\" --directory \"/\" "
> IFS_old=$IFS ; IFS=
> for val in ${files_to_tar} ; do
>     tar_cmd="${tar_cmd} \"${val}\""
> done
> ls -1 ${files_to_tar}
> IFS=$IFS_old
> /bin/bash -c "${tar_cmd}"
>

PS
видимо правильней для wc все же опцию -m вместо -c в данном случае использовать

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

5. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от LSTemp (ok) on 21-Апр-11, 01:14 
>[оверквотинг удален]
> [root@local 111]# cat ./t
> #!/bin/bash
> m='tst/*/*/*'
> echo "mask=$m"
> p=`echo "$m"|sed 's/\/\*//g'`
> echo "path=$p"
> d=`echo "$m"|sed s/[^*]//g|wc -c`
> d=$(($d-1))
> echo "depth=$d"
> find tst -mindepth $d -maxdepth $d -type f

тут конечно должно было быть
find $p -mindepth $d -maxdepth $d -type f
все от маски пути считается

>[оверквотинг удален]
>> for val in ${files_to_tar} ; do
>>     tar_cmd="${tar_cmd} \"${val}\""
>> done
>> ls -1 ${files_to_tar}
>> IFS=$IFS_old
>> /bin/bash -c "${tar_cmd}"
>>
> PS
> видимо правильней для wc все же опцию -m вместо -c в данном
> случае использовать

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от Af. on 21-Апр-11, 21:34 
Нужно это вот зачем: некто пишет в некий файл по одному имени файла/каталога на строку. Скрипт находит этот файл, достаёт оттуда имена/шаблоны как файлов, так и каталогов, пытается скопировать/архивировать/очистить/... найденное. Все имена каталогов абсолютные - удобно при обратном копировании, восстановлении, анализе. Например.

Но периодически нужно для прочих и разных целей формировать из значений переменных шаблон имени файла с пробелами и передавать это как параметр для ls, find и прочих. И шаблон и пробел - шаблоны с пробелами - вызывают у меня сложность, сочетания ситуаций по отдельности - без сложностей.

Экранирование работает, но правильно вынести его в скрипт (не мороча голову оператора), а тогда в скрипте нужно обрабатывать. Вроде вопрос не связан прямо с globbing, во всяком случае его настройка вопрос вроде не решает, если я правильно понял ман. Должны бы быть короткие готовые способы. Причём т.к. вызовы sed, echo, на каждый вызов запуск копии bash занимают чувствительное время, то вероятно можно как-то без них и без доп.вызовов копий bash.

Спасибо за идею счёта "глубины".

P.S. echo "123"|wc -c даёт 4 т.к. эхо добавляет в строку символ '\n'. Если echo -n "123", то будет тройка.

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?"  +/
Сообщение от LSTemp (ok) on 22-Апр-11, 10:01 
>[оверквотинг удален]
> ls, find и прочих. И шаблон и пробел - шаблоны с
> пробелами - вызывают у меня сложность, сочетания ситуаций по отдельности -
> без сложностей.
> Экранирование работает, но правильно вынести его в скрипт (не мороча голову оператора),
> а тогда в скрипте нужно обрабатывать. Вроде вопрос не связан прямо
> с globbing, во всяком случае его настройка вопрос вроде не решает,
> если я правильно понял ман. Должны бы быть короткие готовые способы.
> Причём т.к. вызовы sed, echo, на каждый вызов запуск копии bash
> занимают чувствительное время, то вероятно можно как-то без них и без
> доп.вызовов копий bash.

думаю не так уж и много символов в конечном итоге экранировать придется. можно спокойно обойтись средствами замены символов самого шела. sed тут и правда слишком жирно будет - он для более сложных задач. например экранируем пробелы перед использованием переменной:

[root@local ttt]# aaa='/111/222 333/*/*'; aaa="${aaa// /\ }"; echo "$aaa"
/111/222\ 333/*/*


> Спасибо за идею счёта "глубины".
> P.S. echo "123"|wc -c даёт 4 т.к. эхо добавляет в строку символ
> '\n'. Если echo -n "123", то будет тройка.

ну я это предполжение и написал. просто лень проверять было :)

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру