2013-07-22 3 views
0

Я улучшаю script listing duplicated files, который я написал в прошлом году (см. Второй скрипт, если вы следуете ссылке).match pathname в файле с двойным нулевым байтом-разделителем

Разделитель записи вывода duplicated.log представляет собой нулевой байт вместо возврата каретки \n. Пример:

$> tr '\0' '\n' < duplicated.log 
     12  dir1/index.htm 
     12  dir2/index.htm 
     12  dir3/index.htm 
     12  dir4/index.htm 
     12  dir5/index.htm 

     32  dir6/video.m4v 
     32  dir7/video.m4v 

(в этом примере, пяти файлов dir1/index.htm ... и dir5/index.htm имеют одинаковый md5sum и их размер составляет 12 байт Остальные два файла dir6/video.m4v и dir7/video.m4v имеют такое же md5sum и их размера контента (du.) составляет 32 байта.)

поскольку каждая строка оканчивается нулевым байтом (\0) вместо символа возврата каретки (\n), пустые строки представлены в виде двух последовательных нулевых байтов (\0\0).

Я использую нулевой байт в качестве разделителя строк, потому что путь-имя-файла может содержать символ возврата каретки.

Но, делая, что я столкнулся с этим вопросом:
Как «Grep» все дубликаты указанного файла из duplicated.log?
(например, как получить дубликаты dir1/index.htm?)

мне нужно:

$> ./youranswer.sh "dir1/index.htm" < duplicated.log | tr '\0' '\n' 
     12  dir1/index.htm 
     12  dir2/index.htm 
     12  dir3/index.htm 
     12  dir4/index.htm 
     12  dir5/index.htm 
$> ./youranswer.sh "dir4/index.htm" < duplicated.log | tr '\0' '\n' 
     12  dir1/index.htm 
     12  dir2/index.htm 
     12  dir3/index.htm 
     12  dir4/index.htm 
     12  dir5/index.htm 
$> ./youranswer.sh "dir7/video.m4v" < duplicated.log | tr '\0' '\n' 
     32  dir6/video.m4v 
     32  dir7/video.m4v 

Я думал о каких-то вещах, как:

awk 'BEGIN { RS="\0\0" } #input record separator is double zero byte 
    /filepath/ { print $0 }' duplicated.log 

... но filepath может содержать слэш символы / и многие другие символы (цитаты, возврат каретки ...).

я, возможно, придется использовать perl, чтобы справиться с этой ситуацией ...

Я открыт для любых предложений, вопросов, другие идеи ...

+0

Я не понять, какие имена дублируются в вашем примере –

+0

Hi @glennjackman. Спасибо за отзыв: я обновил свой вопрос, надеюсь, что это будет более понятно, даже если вопрос становится слишком многословным: -/Удачи вам в ответе, наслаждайтесь! ;-) Cheers – olibre

ответ

1

Вы почти там: использовать оператор соответствия ~:

awk -v RS='\0\0' -v pattern="dir1/index.htm" '$0~pattern' duplicated.log 
+0

отлично! Я не думал устанавливать свои переменные с помощью опции '-v'. Очень очень хорошо ;-) Это упростит скрипты 'awk', которые я хочу написать для завершения. Благодаря :-D Cheers – olibre

0

Я просто понял, что я мог бы использовать md5sum вместо имени пути, потому что в моей новой версии скрипта я сохраняю информацию md5sum.

Это новый формат настоящее время я использую:

$> tr '\0' '\n' < duplicated.log 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir1/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir2/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir3/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir4/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir5/index.htm 

    32  fc191f86efabfca83a94d33aad2f87b4 dir6/video.m4v 
    32  fc191f86efabfca83a94d33aad2f87b4 dir7/video.m4v 

gawk и nawk дают желаемого результата:

$> awk 'BEGIN { RS="\0\0" } 
    /89e8a208e5f06c65e6448ddeb40ad879/ { print $0 }' duplicated.log | 
    tr '\0' '\n' 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir1/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir2/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir3/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir4/index.htm 
    12  89e8a208e5f06c65e6448ddeb40ad879 dir5/index.htm 

Но я до сих пор скрываю свои ответы :-)
(этот ответ является лишь обходным путем)


Для любопытных, под новым (ужасным) сценарием в стадии разработки ...

#!/bin/bash 

fifo=$(mktemp -u) 
fif2=$(mktemp -u) 
dups=$(mktemp -u) 
dirs=$(mktemp -u) 
menu=$(mktemp -u) 
numb=$(mktemp -u) 
list=$(mktemp -u) 

mkfifo $fifo $fif2 


# run processing in background 
find . -type f -printf '%11s %P\0' | #print size and filename 
tee $fifo |       #write in fifo for dialog progressbox 
grep -vzZ '^   0 ' |   #ignore empty files 
LC_ALL=C sort -z |     #sort by size 
uniq -Dzw11 |       #keep files having same size 
while IFS= read -r -d '' line 
do         #for each file compute md5sum 
    echo -en "${line:0:11}" "\t" $(md5sum "${line:12}") "\0" 
             #file size + md5sim + file name + null terminated instead of '\n' 
done |        #keep the duplicates (same md5sum) 
tee $fif2 | 
uniq -zs12 -w46 --all-repeated=separate | 
tee $dups | 
#xargs -d '\n' du -sb 2<&- |   #retrieve size of each file 
gawk ' 
function tgmkb(size) { 
    if(size<1024) return int(size) ; size/=1024; 
    if(size<1024) return int(size) "K"; size/=1024; 
    if(size<1024) return int(size) "M"; size/=1024; 
    if(size<1024) return int(size) "G"; size/=1024; 
       return int(size) "T"; } 
function dirname (path) 
     { if(sub(/\/[^\/]*$/, "", path)) return path; else return "."; } 
BEGIN { RS=ORS="\0" } 
!/^$/ { sz=substr($0,0,11); name=substr($0,48); dir=dirname(name); sizes[dir]+=sz; files[dir]++ } 
END { for(dir in sizes) print tgmkb(sizes[dir]) "\t(" files[dir] "\tfiles)\t" dir }' | 
LC_ALL=C sort -zrshk1 > $dirs & 
pid=$! 


tr '\0' '\n' <$fifo | 
dialog --title "Collecting files having same size..." --no-shadow --no-lines --progressbox $(tput lines) $(tput cols) 


tr '\0' '\n' <$fif2 | 
dialog --title "Computing MD5 sum" --no-shadow --no-lines --progressbox $(tput lines) $(tput cols) 


wait $pid 
DUPLICATES=$(grep -zac -v '^$' $dups) #total number of files concerned 
UNIQUES=$( grep -zac '^$' $dups) #number of files, if all redundant are removed 
DIRECTORIES=$(grep -zac  . $dirs) #number of directories concerned 
lins=$(tput lines) 
cols=$(tput cols) 
cat > $menu <<EOF 
--no-shadow 
--no-lines 
--hline "After selection of the directory, you will choose the redundant files you want to remove" 
--menu "There are $DUPLICATES duplicated files within $DIRECTORIES directories.\nThese duplicated files represent $UNIQUES unique files.\nChoose directory to proceed redundant file removal:" 
$lins 
$cols 
$DIRECTORIES 
EOF 
tr '\n"' "_'" < $dirs | 
gawk 'BEGIN { RS="\0" } { print FNR " \"" $0 "\" " }' >> $menu 

dialog --file $menu 2> $numb 
[[ $? -eq 1 ]] && exit 
set -x 
dir=$(grep -zam"$(< $numb)" . $dirs | tac -s'\0' | grep -zam1 . | cut -f4-) 
md5=$(grep -zam"$(< $numb)" . $dirs | tac -s'\0' | grep -zam1 . | cut -f2 ) 

grep -zao "$dir/[^/]*$" "$dups" | 
while IFS= read -r -d '' line 
do 
    file="${line:47}" 
    awk 'BEGIN { RS="\0\0" } '"/$md5/"' { print $0 }' >> $list 
done 

echo -e " 
fifo $fifo \t dups $dups \t menu $menu 
fif2 $fif2 \t dirs $dirs \t numb $numb \t list $list" 

#rm -f $fifo $fif2 $dups $dirs $menu $numb 
Смежные вопросы