Dizin 1'de olan ancak 2 numaralı dizinde olmayan dosyaları karşılaştır?


9

Yapmak istediğim bir bash betiği ile ilgili sorun yaşıyorum

Ben ls bir dizinde olan dosyaları listeler biliyorum ama ben dizin1 ama dizin2 değil dizinleri listelemek istiyorum, ve sonra dizin2 içinde dizin1 olmayan dosyaları listelemek istiyorum.

Hafif bir girişimde denedim:

ls -al | diff directory1 directory2

Neden işe yaramadığını hemen anladım. Herkes tam bir bash nerd dışarı yardımcı olabilir?

Yanıtlar:


9

Bash verildiğinde, bu en kolay olabilir

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

<(command)Sentezleme çalışır komutu bir boru üzerine ve yerine /dev/fdreferans:

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

Bu nedenle yukarıdaki komut ls -aher dizinde çalışır ve çıktılarını dosya bağımsız değişkenleri olarak besler comm, bu da en fazla 3 sütuna kadar çıktı, sekme girintili: yalnızca ilk girişler, her ikisinde girişler, ikincideki girişler. (Yani, her ikisinde de bir sekme ile girintiliyse, yalnızca ikincisinde ise 2 sekme ile girintilidir.) Sütunları sayıya göre de bastırabilirsiniz: comm -1 foo baryalnızca hem ikinci satırdaki hem de ikinci dosyadaki satırları görüntüler, ikincisi bir sekme ile girintili . (Bu en çok, istediğiniz sütun hariç tümü bastırılarak kullanılır: comm -13 foo baryalnızca ortak satırları gösterir.)

İlk dizinde bulunanları istediğiniz göz önüne alındığında,

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

Sadece mevcut olup olmadığından daha fazlasına ihtiyacınız varsa diff -r, ortak dosyalar için diffs ve yalnızca birinde veya diğerinde bulunan dosyalar için tek satırlık bir mesaj çıkaran kullanın .


1
lsdosya adlarında boşluk, sekmeler, satır beslemeleri, arka boşluklar ve benzeri tüm sorunlarla birlikte gelir.
kullanıcı bilinmiyor

1
Bunu karıştıracak tek kişi yeni satırlar ve yine de bu durumda sorunlarınız olduğunu iddia ediyorum. :) Paranoyaksanız kullanın ls -b.
geekosaur

Bulmakla değil, değil mi?
kullanıcı bilinmiyor

Ne ile çağırdığınıza bağlıdır find. Ama benim ana şikayetim find, genellikle oldukça küçük bir sinek olan swat için gerçekten ağır bir balyoz olmasıdır.
geekosaur

Teşekkürler! Bu işe yarıyor ama b dosyasında 'comm' kullanmadan DEĞİLDİR içeriği b çıktı alabilir miyim?
Soju

4

Ve burada saf bir senaryo. Bunlar a ve b dizinleridir:

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

İşte komut:

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

çıktı:

./a
./f/i

A ve b ile a arasındaki dosyaları değiştirin ancak b'deki değil. ! bir olumsuzluktur. -e -varlık testleri. Prosa'da: "../b dosyasında bulunan dosya yoksa test edin".

Not: 'a' olmadan isimler almak için birinciye dalmanız gerekir. İkinci karşılaştırma için cd'ye ihtiyacınız var ../b.


1

Bir grafik aracı tercih ediyorsanız,

xxdiff dir1 dir2 

önce yüklemeniz gerekebilir. Benzer programlar

gtkdiff
tkdiff

Gece yarısı komutanının, alt compare directoriesdizinler için gitmemeniz halinde iyi çalışan bir komut oluşturma özelliği vardır.


1
Hayır, grafik bir araç aramıyorum, yine de teşekkürler!
soju

1

İhmal edilen joinkomutu kullanabilirsiniz . Burada, d1 / ve d2 / olmak üzere iki örnek dizin için bazı kurulumlar vardır; bunların her biri dizine özgü adlara sahip bazı dosyalara ve diğer dizinle ortak adlara sahip bazı dosyalara sahiptir. Bu sadece bir örnektir, bu yüzden birine veya diğerine özgü dosya adlarını ve ortak dosya adlarını göstermek için tek harfli dosya adları kullandım.

# 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/

Benim için böyle dosyalar gösterir:

 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

GÜNCELLEME: joinHangi satırların benzersiz ve hangi satırların ortak olduğuna karar vermek için "boşlukla sınırlandırılmış" ilk alanı kullandığından, dosyalarda boşluk bulunan dosyaları barındırmak için gerçek hayatta farklı şeyler yapmak istersiniz .


Programınızı "d2 / f" adlı bir dosyayla test etmelisiniz. Temel kural: Komut dosyalarında neredeyse hiç ls kullanmayın.
kullanıcı bilinmiyor

Biraz açıklığa kavuşabilir misiniz? D2 / yalnızca bir dosyaya sahip olmalı, d2 / f? Çünkü bunu denedim ve beklendiği gibi çalışıyor.
Bruce Ediger

Ben boşluklar (veya her ikisi de katılmak için varsayılan giriş alanı sınırlayıcıları olduğundan) sekmeleri içeren dosya adları hakkında endişe düşünüyorum . Belki join -t ''(sınırlayıcı yok) bu duruma yardımcı olur.
Chris Johnsen

Evet, öyle d2/fdeğil d2/f . Dosya adlarındaki sekmeler ve yeni satırlar nadirdir, ancak bunlara izin verilir.
kullanıcı bilinmiyor

0

Bunu findve awkbunu çözmek için kullanabilirsiniz .

Aşağıdaki düzen ile:

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

Bölüm Bir:

$ 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

Bölüm iki:

$ 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

Bu bir commçözümle karşılaştırılır :

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

Ve bir joinçözüm için:

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

0

fonksiyonlarımı kullan:

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}
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.