2010-05-28 3 views
2

Имеют документы, хранящиеся в файловой системе, которая включает в себя «ежедневные» каталоги, например. 20050610. В сценарии bash я хочу перечислить файлы в течение нескольких месяцев этих каталогов. Поэтому я запускаю команду поиска find <path>/200506* -type f >> jun2005.lst. Хотелось бы проверить, что этот набор каталогов не является набором нулей перед выполнением команды find. Однако, если я использую if[ -d 200506* ] я получаю «слишком много заданы параметры ошибки. Как я могу обойти это?bash тестирование группы каталогов для существования

ответ

2

Ошибка «слишком много аргументов» возникает из-за того, что существует огромное количество файлов и превышает ограничение аргумента командной строки. Это происходит из-за наличия более чем одной или двух каталогов, которые соответствуют glob. Ваш glob «200506 *» расширяется примерно до «20050601 20050602 20050603 ...», а тест -d ожидает только одного аргумента.

$ mkdir test 
$ cd test 
$ mkdir a1 
$ [ -d a* ] # no error 
$ mkdir a2 
$ [ -d a* ] 
-bash: [: a1: binary operator expected 
$ mkdir a3 
$ [ -d a* ] 
-bash: [: too many arguments 

Ответ на zed_0xff находится на правильном пути, но я хотел бы использовать другой подход:

shopt -s nullglob 
path='/path/to/dirs' 
glob='200506*/' 
outfile='jun2005.lst' 
dirs=("$path"/$glob) # dirs is an array available to be iterated over if needed 
if ((${#dirs[@]} > 0)) 
then 
    echo "directories found" 
    # append may not be necessary here 
    find "$path"/$glob -type f >> "$outfile" 
fi 

Положение котировок в "$path"/$glob против "$path/$glob" имеет важное значение для этой работы.

Edit:

исправление сделано, чтобы исключить файлы, которые соответствуют Glob (поэтому только каталоги включены) и обрабатывать очень необычный случай каталога с именем буквально как Глоба («200506 *»).

+0

Отмечено, что -d ожидает один аргумент. Поскольку проверяемые каталоги «ежедневно» могут быть до 31 в месяц. Я несколько разных «видов» документов и запускаю команды поиска последовательно. найти /а/200506 * >> выходной_файл найти /б/200506 * >> выходной_файл найти /с/200506 * >> выходной_файл Это означает, что если один в середине терпит неудачу, я предполагаю, что после них не выполняются, и весь скрипт терпит неудачу. Это верно? Решение Dennis будет работать в контексте моего сценария. FYI, никакие файлы не соответствуют глобусу по имени, и ни один каталог точно не соответствует glob. –

+0

@ Джейм Джонс: Я не уверен, что я последую за тобой. Что вы можете сделать, это что-то вроде: 'globs = ('200506 * /' '200507 * /' '200508 *'); outfiles = ("jun2005" "jul2005" "aug2005"); subdirs = (a b c); для glob в $ {globs [@]}; do outfilebase = $ {outfiles [i ++]}; для subdir в $ {subdirs [@]}; do path = "/ top/of/path/$ dir"; выходной_файл = "$ outfilebase $ subdir.lst"; dirs = ... [как указано выше] ... if ... find ... else echo «Каталогов не найдено для $ glob под $ subdir"; fi' [untested] –

0
S=200506* 

if [ ${#S} -gt 6 ]; then 
    echo haz filez! 
else 
    echo no filez 
fi 

не очень элегантный один, но без каких-либо внешних инструментов/команд (если не думать из «[», как и внешней)

подсказка, если есть некоторые файлы, совпадающие, то «S» переменный будет содержать имена разделителей с пространством. в противном случае он будет содержать «200506 *» строку самих.

0

Вы можете нас найти ls следующим образом:

if [ -n "$(ls -d | grep 200506)" ]; then 
     # There are directories with this pattern 
    fi 
+0

Возможно, есть обычные файлы с этим шаблоном. – nc3b

+0

@ nc3b: Хороший вызов, '-d' должен помочь, я думаю ... – Bobby

+0

' -d' не ограничивает 'ls' только список каталогов, он просто мешает ему перечислять их содержимое, поэтому' ls -d' list ничего. Вы, вероятно, имеете в виду 'ls -d * /' –

0

Поскольку в большинстве оболочек есть ограничение на длину командной строки: что-нибудь вроде «$ (ls -d | grep 200506) «или/path/200506 * будет угрожать переполнением лимита. Я не уверен, что подстановки и расширения glob относятся к нему в BASH, но я так полагаю. Вам нужно было бы протестировать его и проверить bash документы и источник, чтобы быть уверенным

ответ в упрощая вопрос

find <path>/200506* -type f -exec somescript '{}' \; 

Где somescript это скрипт, который делает тест-то вроде этого, может быть:...

#!/bin/sh 
[ -d "[email protected]" ] && echo "[email protected]" >> june2005.lst 

Passing june2005.lst к скрипту (совет: используйте переменную окружения) и имея дело с любой возможностью, что 200506 * может расширяться до tooo огромного пути к файлу, оставаясь в качестве упражнения для OP;)

Интеграция всего объекта в линию трубопровода или адаптация более общего языка сценариев даст повышение производительности, путем минимизации количества порожденных оболочек. Теперь это будет весело. Вот вам подсказка, используйте -exec и другую программу (awk, perl и т. Д.), Чтобы выполнить тест каталога как часть фильтра с одной строкой и сохранить >> june2005.lst в команде find.

1
prefix="/tmp/path" 
glob="200611*" 
n_dirs=$(find $prefix -maxdepth 1 -type d -wholename "$prefix/$glob" |wc -l) 
if [[ $n_dirs -gt 0 ]];then 
    find $prefix -maxdepth 2 -type f -wholename "$prefix/$glob" 
fi 
Смежные вопросы