2016-09-28 2 views
0

Предположит, что существует каталог «Foo», который содержит несколько файлов:Как хранить NUL-выход программы в сценарии bash?

ls foo: 
1.aa 2.bb 3.aa 4.cc 

Сейчас в Баше скрипте, я хочу, чтобы подсчитать количество файлов с определенным суффиксом «обув», и дисплей их, например:

SUFF='aa' 
FILES=`ls -1 *."$SUFF" foo` 
COUNT=`echo $FILES | wc -l` 
echo "$COUNT files have suffix $SUFF, they are: $FILES" 

проблема: если SUFF='dd', $COUNT также равна 1. После google причина, по которой я нашел, - это когда SUFF='dd', $FILES - пустая строка, а не нулевой вывод программы, которая будет считаться одной строкой на wc. Выход NUL может передаваться только через трубы. Так одно решение:

COUNT=`ls -1 *."$SUFF" foo | wc -l` 

, но это приведет к команде ls выполняется дважды. Поэтому мой вопрос: есть ли еще более элегантный способ достичь этого?

+0

файл-имена заканчиваются 'Foo'? Можете ли вы дать одно такое имя образца? Вы также хотите рекурсивно искать в подкаталогах? – Inian

+0

foo - это каталог. имена файлов заканчиваются на aa, bb, cc. Не нужно искать подкаталоги. – xlwang

ответ

2
$ shopt -s nullglob 
$ FILES=(*) 
$ echo "${#FILES[@]}" 
4 
$ FILES=(*aa) 
$ echo "${#FILES[@]}" 
2 
$ FILES=(*dd) 
$ echo "${#FILES[@]}" 
0 
$ SUFFIX=aa 
$ FILES=(*"$SUFFIX") 
$ echo "${#FILES[@]}" 
2 
$ SUFFIX=dd 
$ FILES=(*"$SUFFIX") 
$ echo "${#FILES[@]}" 
0 
+0

Wow большое объяснение! – 123

+3

@ 123: Это смешно, я его не написал. Вы недавно посетили офтальмолога? –

+0

Есть ли простой способ вывода содержимого FILES один за другим? – xlwang

0

Если вам нужно только количество файлов, я бы на самом деле использовать find для этого:

find '/path/to/directory' -mindepth 1 -maxdepth 1 -name '*.aa' -printf '\n' | wc -l 

Это более надежно, как он обрабатывает правильно имена файлов с разрывами строк. Как это работает, find выводит одну пустую строку для каждого соответствующего файла.

Edit: Если вы хотите сохранить список файлов в массив, вы можете использовать Glob:

GLOBIGNORE=".:.." 
shopt -s nullglob 
FILES=(*aa) 
COUNT=${#arr[@]} 
echo "$COUNT" 
+0

Но я также хочу вывести имена этих файлов позже в скрипте. – xlwang

+1

@Inian Что вы имеете в виду? – redneb

+0

@Inian Это потому, что они выводят только строку новой строки для каждого имени файла, а не фактическое имя файла – 123

0

вы также можете попробовать это;

#!/bin/bash 
SUFF='aa' 
FILES=`ls -1 *."$SUFF" foo` 
FILENAMES=`echo $FILES | awk -F ':' '{print $2}'` 
COUNT=`echo $FILENAMES | wc -w` 
echo "$COUNT files have suffix $SUFF, they are: $FILENAMES" 

если установлена ​​echo $FILES в сценарии, выход foo: 1.aa 2.aa 3.aa так

AWK -F ':' '{печать $ 2}' получает 1.aa 2.aa 3.aa от $ ФАЙЛЫ переменной

wc -w гравюр слово считается

0

Причина в том, что опция nullglob по умолчанию отключена в bash:

Если подходящие имена файлов не найдены, а параметр оболочки nullglob не включен, слово остается неизменным. Если опция nullglob установлена, и совпадений не найдено, слово будет удалено.

Так, просто установите опцию nullglob и запустите ваш код еще раз:

shopt -s nullglob 
SUFF='aa' 
FILES="$(printf '%s\n' foo/*."$SUFF")" 
COUNT="$(printf '%.0s\n' foo/*."$SUFF" | wc -l)" 
echo "$COUNT files have suffix $SUFF, they are: $FILES" 

Или еще лучше:

shopt -s nullglob 
suff='aa' 
files=(foo/*."$suff") 
count=${#file[@]} 
echo "$count files have suffix $suff, they are: ${files[@]}" 
+0

Thx. Но если имена файлов содержат \ n, это может привести к ошибке. – xlwang

+0

@xlwang Хорошо, решено. '% .0s \ n' печатает только новую строку для каждого файла. – sorontar

Смежные вопросы