The OpenNET Project / Index page

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




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! Af., 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

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

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

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

    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"

    • Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! LSTemp, 20:38 , 20-Апр-11 (2)
      > Простите, патч:
      >
       
      > 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}] юзать в зависимости от потребностей.

      • Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! Af., 21:22 , 20-Апр-11 (3)
        > 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}"


        • Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! LSTemp, 23:22 , 20-Апр-11 (4)
          >> 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 в данном случае использовать

          • Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! LSTemp, 01:14 , 21-Апр-11 (5)
            >[оверквотинг удален]
            > [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 в данном
            > случае использовать

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

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

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

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

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

              • Как развернуть '/tmp/aaa bbb/*/*' в список всех имён файлов?, !*! LSTemp, 10:01 , 22-Апр-11 (7)
                >[оверквотинг удален]
                > 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", то будет тройка.

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




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

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