2012-01-20 2 views
2

Я искал способ перечислить файл, который не существует из списка файлов, которые необходимы для существования. Файлы могут существовать в нескольких местах. То, что у меня есть сейчас:Bash скрипт для списка файлов не найден

#!/bin/bash 
fileslist="$1" 
while read fn 
do 
    if [ ! -f `find . -type f -name $fn ` ]; 
    then 
    echo $fn 
    fi 
done < $fileslist 

Если файл не существует, команда find ничего не печатает, и тест не работает. Удаление не и создание условия if then else не решает проблему.

Как распечатать имена файлов, которые не найдены в списке имен файлов?

Новый скрипт:

#!/bin/bash 
fileslist="$1" 
foundfiles="~/tmp/tmp`date +%Y%m%d%H%M%S`.txt" 
touch $foundfiles 
while read fn 
do 
    `find . -type f -name $fn | sed 's:./.*/::' >> $foundfiles` 
done < $fileslist 
cat $fileslist $foundfiles | sort | uniq -u 
rm $foundfiles 
+0

Найти то, что вы можете и дифф со списком можно ожидать? – cdeszaq

+0

@cdeszaq, первое, что я подумал, но не смог придумать способ сделать это без временных файлов или явных bashisms :) –

+0

В настоящее время я создаю список того, что я могу найти, и разницу с файловым списком. Я думал, что смогу автоматизировать это для создания списка файлов, над которыми я должен работать. – user1161495

ответ

1

Попробуйте заменить тело [[ -z "$(find . -type f -name $fn)" ]] && echo $fn. (обратите внимание, что этот код связан с проблемами с именами файлов, содержащими пробелы).

Более эффективное bashism:

diff <(sort $fileslist|uniq) <(find . -type f -printf %f\\n|sort|uniq) 

Я думаю, что вы можете справиться с дифф выход.

+0

Ни то, ни другое! -n работать с результатом поиска, когда он не соответствует имени файла. – user1161495

+0

Работает для меня '$ [[-z" $ (find/tmp -name nosuchfile) "]] && echo нет такой вещи там нет такой вещи там –

+0

Я добавил более эффективную работу. Так как теперь вы все измените, я думаю, что вы можете правильно настроить параметры diff и знать, что делать с выходом –

1

Вот test.bash:

#!/bin/bash 

fn=test.bash 

exists=`find . -type f -name $fn` 
if [ -n "$exists" ] 
then 
    echo Found it 
fi 

Он устанавливает $ существует = в результате находке. if -n проверяет, не является ли результат не нулевым.

+0

Если $ exists имеет значение NULL, вы получите синтаксическую ошибку в выражении «if». – schtever

+0

Я протестировал этот код с файлом, который существовал, и тем, который этого не сделал. Он работал нормально. – Almo

+0

Ни то, ни другое! -n работать с результатом поиска, когда он не соответствует имени файла. – user1161495

1
#!/bin/bash 
fileslist="$1" 
while read fn 
do 
    FPATH=`find . -type f -name $fn` 
    if [ "$FPATH." = "." ] 
    then 
    echo $fn 
    fi 
done < $fileslist 

Вы были близки!

+0

Возникает вопрос о том, что возвращает, когда он не находит соответствия. Как я могу оценить результат? – user1161495

+0

Код выхода из 'find' будет ложным, если он не сработает. Таким образом, вы можете просто «найти». -name "$ fn">/dev/null || echo Не существует: «$ fn» ' – tripleee

0

Повторно find для фильтрации одного файла за один раз очень дорого. Если список файлов совместим с выходом из find, запустить один find и удалить все матчи из списка:

find . -type f | 
fgrep -vxf - "$1" 

Если нет, то, возможно, вы можете массировать выход из find в трубопроводе до fgrep так что он соответствует формату в вашем файле; или, наоборот, массировать данные в вашем файле в find -совместимо.

+0

Я ищу 20 или 100 файлов, но структура каталогов, в которой я ищу, содержит почти 1500 файлов. Я не думаю, что это сработает. – user1161495

1

Дайте этому попытку:

find -type f -print0 | grep -Fzxvf - requiredfiles.txt 

-print0 и -z защиты от имен файлов, которые содержат символы новой строки. Если ваши утилиты не имеют этих параметров, а ваши имена не содержат строк новой строки, вы должны быть в порядке.

+0

Мне нравится идея, но я не думаю, что опция -v работает так, как – marinara

+0

получил эту хорошую работу с петлей bash и grep -Fzqa. это также довольно быстро с 10K-файлами – marinara

0

Я использую этот сценарий, и это работает для меня

#!/bin/bash 
fileslist="$1" 
found="Found:" 
notfound="Not found:" 
len=`cat $1 | wc -l` 
n=0; 

while read fn 
do 
    # don't worry about this, i use it to display the file list progress 
    n=$((n + 1)) 
    echo -en "\rLooking $(echo "scale=0; $n * 100/$len" | bc)% " 
    if [ $(find/-name $fn | wc -l) -gt 0 ] 
    then 
    found=$(printf "$found\n\t$fn") 
    else 
    notfound=$(printf "$notfound\n\t$fn") 
    fi 
done < $fileslist 

printf "\n$found\n$notfound\n" 

Линия подсчитывает количество строк, и если его больше, чем 0 находка была успешной. Это ищет все на hdd. Вы можете заменить/на. только для текущего каталога.

$(find/-name $fn | wc -l) -gt 0 

Тогда я просто запустить его с файлами в списке файлов, разделенных символом новой строки

./search.sh files.list 
Смежные вопросы