उन फ़ाइलों की तुलना करें जो निर्देशिका 1 में हैं, लेकिन निर्देशिका 2 नहीं है?


9

मैं एक बैश स्क्रिप्ट से परेशान हूं, जिसे मैं बनाना चाहता हूं

मुझे पता है कि ls उन फ़ाइलों को सूचीबद्ध करेंगे जो एक निर्देशिका में हैं, लेकिन मैं चाहता हूं कि वे उन निर्देशिकाओं को सूचीबद्ध करें जो निर्देशिका 1 में हैं, लेकिन निर्देशिका 2 में नहीं हैं, और फिर निर्देशिका 2 में उन फ़ाइलों को सूचीबद्ध करें जो निर्देशिका 1 में नहीं हैं।

एक असफल प्रयास में, मैंने कोशिश की:

ls -al | diff directory1 directory2

जल्दी से मुझे एहसास हुआ कि यह काम क्यों नहीं किया। किसी को भी मदद कर सकते हैं कुल बकवास बाहर बेवकूफ?

जवाबों:


9

बैश को देखते हुए, यह सबसे आसान हो सकता है

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

<(command)अभिव्यक्ति रन कमान एक पाइप के ऊपर और एक विकल्प /dev/fdसंदर्भ:

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

इसलिए ऊपर दी गई कमांड ls -aप्रत्येक डायरेक्टरी पर चलती है और फाइल आउटपुट के रूप में उनके आउटपुट को फीड करती है comm, जो 3 कॉलम, टैब-इंडेंटेड तक आउटपुट करता है: केवल पहली में एंट्री, दोनों में एंट्री, दूसरे में एंट्री। (अर्थात, यदि यह दोनों में है, तो यह एक टैब द्वारा इंडेंट किया जाता है, यदि यह केवल दूसरे में है तो यह 2 टैब द्वारा इंडेंट किया जाता है।) आप कॉलम को संख्या से भी दबा सकते हैं: comm -1 foo barदोनों को केवल लाइनों और दूसरी फ़ाइल में लाइनों को प्रदर्शित करता है। एक टैब द्वारा बाद वाला इंडेंट । (यह आमतौर पर सभी को दबाने के द्वारा उपयोग किया जाता है, लेकिन आप जो कॉलम चाहते हैं: comm -13 foo barआम में केवल लाइनें दिखाता है।)

यह देखते हुए कि आप पहली निर्देशिका में वे चाहते हैं, जो अनुवाद करता है

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

यदि आपको जरूरत है कि क्या यह मौजूद है, उपयोग से अधिक है diff -r, जो आउटपुट आम फाइलों में अलग-अलग होगा और केवल एक या दूसरे में मिली फाइलों के लिए एक-लाइन संदेश।


1
lsसफेद स्थान, टैब, लाइनफीड, बैकस्पेस और इस तरह के फ़ाइल नाम के साथ सभी समस्याओं के साथ आएगा।
उपयोगकर्ता अज्ञात

1
केवल वही है जो इस बात को भ्रमित करेगा, और मैं आपको इस मामले में किसी भी तरह की समस्या होने का तर्क दूंगा। :) यदि आप पागल हैं, का उपयोग करें ls -b
गीकॉउसर

खोजने के साथ नहीं, क्या मैं?
उपयोगकर्ता अज्ञात

इस बात पर निर्भर करता है कि आप किसके साथ निवेश कर रहे हैं find। लेकिन इसके बारे findमें मेरी मुख्य शिकायत यह है कि यह वास्तव में भारी मक्खी है जो आमतौर पर एक छोटी मक्खी है।
गीकॉउसर

धन्यवाद! यह काम करता है, लेकिन क्या मैं इसे उन सामग्री के आउटपुट के लिए प्राप्त कर सकता हूं जो फ़ाइल b में हैं जो 'comm' का उपयोग किए बिना फ़ाइल में नहीं हैं?
सूजू

4

और यहाँ एक शुद्ध स्क्रिप्ट। ये निर्देशिका और बी हैं:

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

यहाँ आदेश है:

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

उत्पादन:

./a
./f/i

फ़ाइलों के लिए a और b स्वैप करें लेकिन b में नहीं। ! एक नकार है। -मैं परीक्षण के लिए -existance। Prosa में: "टेस्ट करें यदि मौजूद फाइल में मौजूद नहीं है ../b"।

नोट: आपको 'a' के बिना नाम पाने के लिए पहले गोता लगाना होगा। दूसरा तुलना के लिए आप सीडी के लिए है ../b


1

यदि आप एक ग्राफिकल टूल पसंद करते हैं, तो उपयोग करें

xxdiff dir1 dir2 

आपको पहले इसे स्थापित करने की आवश्यकता हो सकती है। इसी तरह के कार्यक्रम हैं

gtkdiff
tkdiff

आधी रात के कमांडर के पास एक compare directoriesकमांड बिल्ड होता है, जो अच्छा काम करता है, अगर आप उप-अध्यक्षों के लिए नहीं जाते हैं।


1
नहीं, मैं एक ग्राफिकल टूल की तलाश में नहीं हूं, हालांकि धन्यवाद!
सूजू

1

आप उपेक्षित joinकमांड का उपयोग कर सकते हैं । यहां दो उदाहरण निर्देशिकाओं के लिए कुछ सेटअप, d1 / और d2 /, जिनमें से प्रत्येक में निर्देशिका के लिए विशिष्ट नाम के साथ कुछ फाइलें हैं, और कुछ फाइलें अन्य निर्देशिका के नाम के साथ समान हैं। यह केवल एक उदाहरण है, इसलिए मैंने फ़ाइल नामों को एक या दूसरे के लिए विशिष्ट, और सामान्य रूप से फ़ाइल नामों को चित्रित करने के लिए एकल-अक्षर फ़ाइल नामों का उपयोग किया।

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

मेरे लिए, यह इस तरह से फाइल दिखाता है:

 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

अद्यतन: आप वास्तविक जीवन में अलग-अलग चीजें करना चाहते हैं ताकि उनमें व्हाट्सएप के साथ फाइलें मिलें, क्योंकि joinपहली पंक्ति "व्हाट्सएप द्वारा सीमांकित" का उपयोग करती है ताकि यह तय किया जा सके कि कौन सी लाइनें अनइक हैं और कौन सी लाइनें आम हैं।


आपको "d2 / f" नामक फ़ाइल के साथ अपने कार्यक्रम का परीक्षण करना चाहिए। अंगूठे का नियम: लिपियों में लगभग कभी भी एलएस का उपयोग न करें।
उपयोगकर्ता अज्ञात

क्या आप थोड़ा स्पष्ट कर सकते हैं? D2 / केवल एक फ़ाइल होनी चाहिए, d2 / f? क्योंकि मैंने यह कोशिश की, और यह उम्मीद के मुताबिक काम करता है।
ब्रूस एडिगर

मुझे लगता है कि वह उन फ़ाइलनामों के बारे में चिंतित हैं जिनमें रिक्त स्थान (या टैब शामिल हैं, क्योंकि दोनों डिफ़ॉल्ट इनपुट फ़ील्ड में शामिल होने के लिए सीमांकक हैं )। शायद join -t ''(कोई परिसीमन) उस मामले में मदद नहीं करेगा।
क्रिस जॉन्सन

हाँ, यह है नहीं d2/fलेकिन d2/f । फ़ाइल नाम में टैब और नई लाइनें दुर्लभ हैं, लेकिन अनुमति दी गई है।
उपयोगकर्ता अनजान

0

आप इसका उपयोग कर सकते हैं findऔर awkइसे हल कर सकते हैं ।

निम्नलिखित लेआउट के साथ:

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

भाग एक:

$ 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

भाग दो:

$ 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

यह एक commसमाधान की तुलना करता है :

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

और एक joinसमाधान के लिए:

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

0

मेरे कार्यों का उपयोग करें:

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}
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.