¿Comparar los files que están en el directory 1 pero no en el directory 2?

Estoy teniendo problemas con un script bash que quiero hacer

Sé que listré los files que están en un directory pero quiero que liste los directorys que están en el directory1 pero NO en el directory2, y luego los files en el directory2 que NO están en el directory1.

En un bash débil, intenté:

ls -al | diff directory1 directory2 

Rápidamente me di count de por qué no funcionó. ¿Alguien puede ayudar a un bash nerd total?

Dado bash, esto podría ser más fácil ya que

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

La expresión <(command) ejecuta el command sobre una tubería y sustituye una reference /dev/fd :

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

Entonces, el command anterior ejecuta ls -a en cada directory y alimenta sus salidas como arguments de file a comm , que genera hasta 3 columnas, con sangría de tabulación: solo inputs en el primero, inputs en ambas, inputs en el segundo. (Es decir, si está en ambos, se sangra mediante una pestaña, si solo está en el segundo, está sangrada con 2 tabs). También puede suprimir columnas por número: comm -1 foo bar muestra solo las líneas en ambos y líneas en el segundo file, este último sangrado por una pestaña. (Esto se usa comúnmente al suprimir todo less la columna que desea: comm -13 foo bar muestra solo las líneas en común).

Dado que quiere aquellos en el primer directory, eso se traduce en

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

Si necesita algo más que solo si está presente, use diff -r , que generará diffs para los files en común y un post de una línea para los files que se encuentran solo en uno u otro.

Y aquí un guión puro. Estos son los directorys a y b:

 find ab 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 

Aquí está el command:

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

salida:

 ./a ./f/i 

Cambie ayb por files en a, pero no en b. Los ! es una negación -e testings de -existencia. En prosa: "Prueba si no existe el file encontrado en a en ../b".

Nota: Tienes que sumergirte en una primera, para get nombres sin 'a'. Para la segunda comparación, debe cd ../b .

Si prefiere una herramienta gráfica, use

 xxdiff dir1 dir2 

Es posible que tengas que instalarlo primero. Progtwigs similares son

 gtkdiff tkdiff 

El comandante de medianoche tiene una compilation de commands de compare directories , que funciona bien, si no vas por subdirectorys.

Podría usar el command de join descuidado. Aquí hay una configuration para dos directorys de ejemplo, d1 / y d2 /, cada uno de los cuales tiene algunos files con nombres exclusivos del directory, y algunos files con nombres en común con el otro directory. Esto es solo un ejemplo, así que usé nombres de files de una sola letra para ilustrar nombres de files únicos para uno u otro, y nombres de files en común.

 # set up for example mkdir d1 d2 for name in abcdefgh do touch d1/$name done for name in efghijkl 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 mí, muestra files 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 

ACTUALIZACIÓN: desearía hacer cosas diferentes en la vida real para acomodar files con espacios en blanco en ellos, ya que join utiliza el primer campo "delimitado por espacios en blanco" para decidir qué líneas son únicas y qué líneas son comunes.

Puedes usar find y awk para resolver esto.

Con el siguiente layout:

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

Parte uno:

 $ find ab -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 

La segunda parte:

 $ find ba -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 

Esto se compara con una solución de comm :

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

Y a una solución de join :

 $ join -v1 <(ls a) <(ls b) 3 f2 $ join -v2 <(ls a) <(ls b) 2 f3 

usa mis funciones:

 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} '\033[1;30m') n=$(${print} '\033[0;30m') R=$(${print} '\033[1;31m') r=$(${print} '\033[0;31m') G=$(${print} '\033[1;32m') g=$(${print} '\033[0;32m') Y=$(${print} '\033[1;33m') y=$(${print} '\033[0;33m') B=$(${print} '\033[1;34m') b=$(${print} '\033[0;34m') M=$(${print} '\033[1;35m') m=$(${print} '\033[0;35m') C=$(${print} '\033[1;36m') c=$(${print} '\033[0;36m') W=$(${print} '\033[1;37m') w=$(${print} '\033[0;37m') END=$(${print} '\033[0m') # background RN=$(${print} '\033[6;40m') Rn=$(${print} '\033[40m') RR=$(${print} '\033[6;41m') Rr=$(${print} '\033[41m') RG=$(${print} '\033[6;42m') Rg=$(${print} '\033[42m') RY=$(${print} '\033[6;43m') Ry=$(${print} '\033[43m') RB=$(${print} '\033[6;44m') Rb=$(${print} '\033[44m') RM=$(${print} '\033[6;45m') Rm=$(${print} '\033[45m') RC=$(${print} '\033[6;46m') Rc=$(${print} '\033[46m') RW=$(${print} '\033[6;47m') Rw=$(${print} '\033[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(\$2,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} }