Compare os arquivos que estão no diretório 1, mas não no diretório 2?

9

Estou tendo problemas com um script bash que quero fazer

Sei que ls listarei os arquivos que estão em um diretório, mas quero listar os diretórios que estão no diretório1, mas NÃO no diretório2, e, em seguida, listar os arquivos no diretório2 que NÃO estão no diretório1.

Em uma tentativa fraca, tentei:

ls -al | diff directory1 directory2

Rapidamente, percebi porque não funcionou. Alguém pode ajudar um nerd total?

    
por soju 11.03.2011 / 01:18

6 respostas

9

Dado o bash, isso pode ser mais fácil como

$ comm <(ls -a dir1) <(ls -a dir2)

A expressão <(command) executa o comando em um canal e substitui uma referência /dev/fd :

mress:10018 Z$ echo <(ls)
/dev/fd/11

Portanto, o comando acima executa ls -a em cada diretório e alimenta suas saídas como argumentos de arquivo para comm , que gera até 3 colunas, recuadas por tabulação: entradas somente nas primeiras entradas em ambas entradas do arquivo. segundo. (Ou seja, se estiver em ambos, será recuado por uma tabulação, se estiver apenas no segundo, será recuado por duas guias.) Você também pode suprimir colunas por número: comm -1 foo bar exibe apenas as linhas em ambas e as linhas na guia. segundo arquivo, o último recuado por uma guia. (Isso é mais comumente usado suprimindo todos, menos a coluna que você deseja: comm -13 foo bar mostra apenas as linhas em comum.)

Dado que você quer aqueles no primeiro diretório, isso se traduz em

$ comm -23 <(ls -a dir1) <(ls -a dir2)

Se você precisar de mais do que apenas se ele estiver presente, use diff -r , que produzirá diffs para os arquivos em comum e uma mensagem de uma linha para os arquivos encontrados apenas em um ou outro.

    
por 11.03.2011 / 01:51
4

E aqui um roteiro puro. Estes são os diretórios a e b:

find a b
a
a/a
a/b
a/c
a/f
a/f/h
a/f/i
b
b/b
b/c
b/d
b/f
b/f/g
b/f/h

Aqui está o comando:

cd a
find ./ -exec test ! -e ../b/{} ";" -print 

saída:

./a
./f/i

Troque a e b para arquivos em um, mas não em b. O ! é uma negação. -e testes para -existência. Em prosa: "Teste se não existe o arquivo encontrado em um ../b".

Nota: Você tem que mergulhar em um primeiro, para obter nomes sem 'a'. Para a segunda comparação, você precisa cd ../b .

    
por 11.03.2011 / 01:42
1

Se você preferir uma ferramenta gráfica, use

xxdiff dir1 dir2 

você pode precisar instalá-lo primeiro. Programas similares são

gtkdiff
tkdiff

O comando da meia-noite tem um comando compare directories construído, o que funciona bem, se você não quiser subdirecionar.

    
por 11.03.2011 / 01:22
1

Você pode usar o comando join negligenciado. Aqui estão algumas configurações para dois diretórios de exemplo, d1 / e d2 /, cada um dos quais possui alguns arquivos com nomes exclusivos para o diretório e alguns arquivos com nomes em comum com o outro diretório. Este é apenas um exemplo, por isso usei nomes de arquivo de uma única letra para ilustrar nomes de arquivos exclusivos de um ou de outro e nomes de arquivos em comum.

# set up for example
mkdir d1 d2
for name in a  b  c  d  e  f  g  h
do
    touch d1/$name
done
for name in e f g h i j k l
do
    touch d2/$name
done

ls -1 d1 > d1.out   # That's "minus one" not "minus ell"
ls -1 d2 > d2.out
join d1.out d2.out       # files common to both d1/ and d2/
join -v 1 d1.out d2.out  # files only in directory d1/
join -v 2 d1.out d2.out  # files only in directory d2/

Para mim, mostra arquivos como este:

 5:51PM 100 % join d1.out d2.out
e
f
g
h
 5:51PM 101 % join -v 1 d1.out d2.out
a
b
c
d
 5:52PM 102 % join -v 2 d1.out d2.out
i
j
k
l

UPDATE: Você gostaria de fazer coisas diferentes na vida real para acomodar arquivos com espaço em branco, já que join usa o primeiro campo "delimitado por espaço em branco" para decidir quais linhas são uniqe e quais linhas são comuns. / p>     

por 11.03.2011 / 01:55
0

Você pode usar find e awk para resolver isso.

Com o seguinte layout:

$ mkdir a b a/1 b/1 b/2 a/3
$ touch a/f1 b/f1 a/f2 b/f3

Primeira parte:

$ find a b -mindepth 1 -maxdepth 1 -type d | \
    awk -F/ ' { if (!w[$1]) w[$1]=++i; if (w[$1]>1) b[$2]=1; else a[$2]=1; }
          END { for (x in a) if (!b[x]) print x }'
3

Parte dois:

$ find b a -mindepth 1 -maxdepth 1 -type f | \
    awk -F/ ' { if (!w[$1]) w[$1]=++i; if (w[$1]>1) b[$2]=1; else a[$2]=1; }
          END { for (x in a) if (!b[x]) print x }'
f3

Isso se compara a uma comm solution:

$ comm -23 <(ls a) <(ls b)    
3
f2
$ comm -13 <(ls a) <(ls b)
2
f3

E para uma solução join :

$ join -v1 <(ls a) <(ls b)
3
f2
$ join -v2 <(ls a) <(ls b)
2
f3
    
por 11.03.2011 / 08:23
0

use minhas funções:

setColors ()
{
# http://wiki.bash-hackers.org/scripting/terminalcodes
set -a
which printf >/dev/null 2>&1 && print=printf || print=print # Mandriva doesn't know about printf

hide='eval tput civis'
show='eval tput cnorm'
CLS=$(tput clear)
bel=$(tput bel)

case ${UNAME} in
AIX)
# text / foreground
N=$(${print} '3[1;30m')
n=$(${print} '3[0;30m')
R=$(${print} '3[1;31m')
r=$(${print} '3[0;31m')
G=$(${print} '3[1;32m')
g=$(${print} '3[0;32m')
Y=$(${print} '3[1;33m')
y=$(${print} '3[0;33m')
B=$(${print} '3[1;34m')
b=$(${print} '3[0;34m')
M=$(${print} '3[1;35m')
m=$(${print} '3[0;35m')
C=$(${print} '3[1;36m')
c=$(${print} '3[0;36m')
W=$(${print} '3[1;37m')
w=$(${print} '3[0;37m')
END=$(${print} '3[0m')

# background
RN=$(${print} '3[6;40m')
Rn=$(${print} '3[40m')
RR=$(${print} '3[6;41m')
Rr=$(${print} '3[41m')
RG=$(${print} '3[6;42m')
Rg=$(${print} '3[42m')
RY=$(${print} '3[6;43m')
Ry=$(${print} '3[43m')
RB=$(${print} '3[6;44m')
Rb=$(${print} '3[44m')
RM=$(${print} '3[6;45m')
Rm=$(${print} '3[45m')
RC=$(${print} '3[6;46m')
Rc=$(${print} '3[46m')
RW=$(${print} '3[6;47m')
Rw=$(${print} '3[47m')

HIGH=$(tput bold)
SMUL=$(tput smul)
RMUL=$(tput rmul)
BLINK=$(tput blink)
REVERSE=$(tput smso)
REVERSO=$(tput rmso)
;;
*)
# text / foreground
n=$(tput setaf 0)
r=$(tput setaf 1)
g=$(tput setaf 2)
y=$(tput setaf 3)
b=$(tput setaf 4)
m=$(tput setaf 5)
c=$(tput setaf 6)
w=$(tput setaf 7)
N=$(tput setaf 8)
R=$(tput setaf 9)
G=$(tput setaf 10)
Y=$(tput setaf 11)
B=$(tput setaf 12)
M=$(tput setaf 13)
C=$(tput setaf 14)
W=$(tput setaf 15)
END=$(tput sgr0)

HIGH=$(tput bold)
SMUL=$(tput smul)
RMUL=$(tput rmul)
BLINK=$(tput blink)
REVERSE=$(tput smso)
REVERSO=$(tput rmso)

# background
Rn=$(tput setab 0)
Rr=$(tput setab 1)
Rg=$(tput setab 2)
Ry=$(tput setab 3)
Rb=$(tput setab 4)
Rm=$(tput setab 5)
Rc=$(tput setab 6)
Rw=$(tput setab 7)
RN=$(tput setab 8)
RR=$(tput setab 9)
RG=$(tput setab 10)
RY=$(tput setab 11)
RB=$(tput setab 12)
RM=$(tput setab 13)
RC=$(tput setab 14)
RW=$(tput setab 15)
;;
esac

BLUEf="${B}"
BLUE="${b}"
REDf="${R}"
RED="${r}"
GREENf="${G}"
GREEN="${g}"
YELLOWf="${Y}"
YELLOW="${y}"
MANGENTAf="${M}"
MANGENTA="${m}"
WHITEf="${W}"
WHITE="${w}"
CYANf="${C}"
CYAN="${c}"

OK="${RG}${n}OK${END}"
KO="${RR}${n}KO${END}"
NA="${N}NA${END}"

COLORIZE='eval sed -e "s/{END}/${END}/g" -e "s/{HIGH}/${HIGH}/g" -e "s/{SMUL}/${SMUL}/g" -e "s/{RMUL}/${RMUL}/g" -e "s/{BLINK}/${BLINK}/g" -e "s/{REVERSE}/${REVERSE}/g" -e "s/{REVERSO}/${REVERSO}/g"'
LOWS=' -e "s/{n}/${n}/g" -e "s/{r}/${r}/g" -e "s/{g}/${g}/g" -e "s/{y}/${y}/g" -e "s/{b}/${b}/g" -e "s/{m}/${m}/g" -e "s/{c}/${c}/g" -e "s/{w}/${w}/g"'
HIGHS=' -e "s/{N}/${N}/g" -e "s/{R}/${R}/g" -e "s/{G}/${G}/g" -e "s/{Y}/${Y}/g" -e "s/{B}/${B}/g" -e "s/{M}/${M}/g" -e "s/{C}/${C}/g" -e "s/{W}/${W}/g"'
REVLOWS=' -e "s/{Rn}/${Rn}/g" -e "s/{Rr}/${Rr}/g" -e "s/{Rg}/${Rg}/g" -e "s/{Ry}/${Ry}/g" -e "s/{Rb}/${Rb}/g" -e "s/{Rm}/${Rm}/g" -e "s/{Rc}/${Rc}/g" -e "s/{Rw}/${Rw}/g"'
REVHIGHS=' -e "s/{RN}/${RN}/g" -e "s/{RR}/${RR}/g" -e "s/{RG}/${RG}/g" -e "s/{RY}/${RY}/g" -e "s/{RB}/${RB}/g" -e "s/{RM}/${RM}/g" -e "s/{RC}/${RC}/g" -e "s/{RW}/${RW}/g"'
# COLORIZE Usage:
# command |${COLORIZE} ${LOWS} ${HIGHS} ${REVLOWS} ${REVHIGHS}
}

# diffDir shows diff content between two dirs
diffDir()
{
(($# < 2)) && echo "${W}diffDir ${C}<leftDir> <rightDir> ${c}[[[${C}miss|diff|same|all*${c}] [${C}uniq${c}]] [${C}resolv${c}]]${END}" && return 99
local showWhat=all
local UNIQ=false
local RESOLV=false
local uniqNames="cat"
local resolvPaths="cat"
local rightDirContent=/tmp/diffDir.$$.tmp

local leftDir=$1
local rightDir=$2
case $3 in
mis*) showWhat=miss ;;
dif*|siz*) showWhat=diff ;;
sam*) showWhat=same ;;
*)  showWhat=all ;;
esac
UNIQ=${4:+true}
RESOLV=${5:+true}

[ "$4" == "uniq" ] && uniqNames="awk '/~/ {n=split(\,libname,\".\");print libname[1]}'|sort|uniq"
[ "$5" == "resolv" ] && resolvPaths='while read _lib;do /bin/ls ${leftDir}/${_lib}.*;done'

ls -lqF ${rightDir}| awk 'NR>1 {if ($(NF-1) == "->") {printf "%s %s->%s\n",$5,$(NF-2),$NF} else {print $5,$NF}}' | sort -k 2 >${rightDirContent}
ls -lqF ${leftDir}| awk 'NR>1 {if ($(NF-1) == "->") {printf "%s %s->%s\n",$5,$(NF-2),$NF} else {print $5,$NF}}' | sort -k 2 | join -a1 -a2 -1 2 -2 2 -o 1.2,1.1,2.1,2.2 -e 0 - ${rightDirContent} |\
awk -v leftDir=${leftDir} -v rightDir=${rightDir} -v showWhat=${showWhat} '
function commas(d) {
  # http://www.staff.science.uu.nl/~oostr102/docs/nawk/nawk_65.html
  d = d ""
  gsub(",","",d)
  point = index(d,".") - 1
  if (point < 0) point = length(d)
  while (point > 3) {
    point -= 3
    d = substr(d,1,point)","substr(d,point + 1)
  }
  return d
}
BEGIN {i=1;leftWidth=20;rightWidth=20;totalSizeLeft=0;totalSizeRight=0;sep="----------------------------------------------------------------"}
{
leftColor[i]="{w}";sign[i]="="
if ($2==$3) {if (showWhat!="all" && showWhat!="same") {next} else {leftColor[i]="{N}"}} else {leftColor[i]="{y}";sign[i]="~"}
if ($1 ~ "->") {leftColor[i]="{c}"}
leftName[i]=$1;leftSize[i]=$2;rightSize[i]=$3;rightName[i]=$4
middleColor[i]=leftColor[i]
if (leftName[i]=="0") {leftSize[i]="";leftName[i]="";middleColor[i]="{w}";sign[i]="#"} else {totalLeft++;totalSizeLeft+=leftSize[i]}
if (rightName[i]=="0") {rightSize[i]="";rightName[i]="";leftColor[i]=middleColor[i]="{w}";sign[i]="#"} else {totalRight++;totalSizeRight+=rightSize[i]}
if (showWhat=="same" && sign[i]!="=") {next}
if (showWhat=="miss" && sign[i]!="#") {next}
if (showWhat=="diff" && sign[i]!="~") {next}
if (length($1) > leftWidth) {leftWidth=length($1)}
if (length($4) > rightWidth) {rightWidth=length($4)}
if (leftName[i] ~ "->") {middleColor[i]="{c}"}
i++
}
END {
if (i==1) {print "identical"} else {
printf "%s %."leftWidth"s %.14s : %.14s %."rightWidth"s\n","{c}",sep,sep,sep,sep
printf "%s %"leftWidth"s %14s : %14s %-"rightWidth"s\n","{c}",leftDir,"","",rightDir
for (n=1; n<i; n++) {
  printf "%s %"leftWidth"s %14s %s%s %-14s %-"rightWidth"s\n",leftColor[n],leftName[n],commas(leftSize[n]),middleColor[n],sign[n],commas(rightSize[n]),rightName[n]
}
printf "%s %."leftWidth"s %.14s : %.14s %."rightWidth"s\n","{W}",sep,sep,sep,sep
printf "%s %"leftWidth"s %14s : %-14s %-"rightWidth"s{END}\n","{W}","total : "totalLeft,commas(totalSizeLeft),commas(totalSizeRight),totalRight
}
}' |\
${COLORIZE} ${LOWS} ${HIGHS} |\
eval ${uniqNames} |\
eval ${resolvPaths}

rm -f ${rightDirContent}
}
    
por 23.05.2013 / 12:13