Find the Files Existing in One Directory But Not in the Other

Find the files existing in one directory but not in the other


diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

Explanation:

  • diff -r dir1 dir2 shows which files are only in dir1 and those only in dir2 and also the changes of the files present in both directories if any.

  • diff -r dir1 dir2 | grep dir1 shows which files are only in dir1

  • awk to print only filename.

List files that are in directory1 but NOT in directory2 and vice versa?

a bit crude - but the easiest way I always use is (can play with the diff params, I typically use different grep

diff -rcw DIR1 DIR2| grep ^Only

then you can sort and format as you like

Revised to format (less efficient as we are running diff twice here ... easily solved)

echo files only in $dir1
LST=$(diff ${dir1} ${dir2}| grep "^Only in ${dir1}"| sed 's@^.*: @@')
(cd ${dir1}; ls -l ${LST})

echo files only in $dir2
LST=$(diff ${dir1} ${dir2}| grep "^Only in ${dir2}"| sed 's@^.*: @@')
(cd ${dir2}; ls -l ${LST})

Expanding on the sed expression above:

s=search and replace

the three '@' are separating the expressions (this is TRADITIONALLY done with '/')

^ matches the beginning of a line (forces the rest not to match elsewhere)
. means any character

* means the previous expression (.==match any char) 0-N times
": " is what I matched on from the diff output "Only in X: "

Look Mommy, no hands - now without 'sed' its beginning to be less and less crude

XIFS="${IFS}"
IFS=$'\n\r'
for DIFFLINE in $(diff ${dir1} ${dir2}|grep ^Only); do
case "${DIFFLINE}" in
"Only in ${dir1}"*)
LST1="${LST1} ${DIFFLINE#*:}"
;;
"Only in ${dir2}"*)
LST2+="${DIFFLINE#*:}"
;;
esac
done
IFS="${XIFS}"

echo files only in $dir1
(cd ${dir1}; ls -l ${LST1})

echo files only in $dir2
(cd ${dir2}; ls -l ${LST2})

You will probably want to know about IFS ... it needs some reading in the bash manual, but its basically the field separator characters ... by default they include spaces and I don't want the loop to be fed with fractions of lines, just complete lines - so for the duration of the loop I override the default IFS to just newlines and carriage returns.

BTW maybe your professor is reading stackoverflow, maybe next you wont be allowed to use semicolons ;-) ... (back to 'man bash' ... BTW if you do 'man bash' do it in emacs, makes much easier to read IMO)

in bash find all files in flat directory that don't exist in another directory tree


# A
# ├── blue file.png
# └── red file.png
# B
# └── small
# └── red file.png

$ comm -23 <( find A -type f -printf '%f\n' | sort | uniq ) <( find B -type f -printf '%f\n' | sort | uniq )
blue file.png

If your find lacks -printf, you can try:

comm -23 <( find A -type f -exec basename {} \; | sort | uniq ) <( find B -type f -exec basename {} \; | sort | uniq )

How to only find files in a given directory, and ignore subdirectories using bash

If you just want to limit the find to the first level you can do:

 find /dev -maxdepth 1 -name 'abc-*'

... or if you particularly want to exclude the .udev directory, you can do:

 find /dev -name '.udev' -prune -o -name 'abc-*' -print

How to list only files and not directories of a directory Bash?

Using find:

find . -maxdepth 1 -type f

Using the -maxdepth 1 option ensures that you only look in the current directory (or, if you replace the . with some path, that directory). If you want a full recursive listing of all files in that and subdirectories, just remove that option.

Find all files in a directory that are not directories themselves

If you want test.log, test2.log, and file2 then:

find . -type f

If you do not want file2 then:

find . -maxdepth 1 -type f

How do I exclude a directory when using `find`?

Use the -prune primary. For example, if you want to exclude ./misc:

find . -path ./misc -prune -o -name '*.txt' -print

To exclude multiple directories, OR them between parentheses.

find . -type d \( -path ./dir1 -o -path ./dir2 -o -path ./dir3 \) -prune -o -name '*.txt' -print

And, to exclude directories with a specific name at any level, use the -name primary instead of -path.

find . -type d -name node_modules -prune -o -name '*.json' -print


Related Topics



Leave a reply



Submit