user1161495
user1161495

Reputation: 77

Bash script to list files not found

I have been looking for a way to list file that do not exist from a list of files that are required to exist. The files can exist in more than one location. What I have now:

#!/bin/bash
fileslist="$1"
while read fn
do
  if [ ! -f `find . -type f -name $fn ` ];
  then
   echo $fn
  fi
done < $fileslist

If a file does not exist the find command will not print anything and the test does not work. Removing the not and creating an if then else condition does not resolve the problem.

How can i print the filenames that are not found from a list of file names?

New script:

#!/bin/bash
fileslist="$1"
foundfiles="~/tmp/tmp`date +%Y%m%d%H%M%S`.txt"
touch $foundfiles
while read fn
do
  `find . -type f -name $fn | sed 's:./.*/::' >> $foundfiles`
done < $fileslist
cat $fileslist $foundfiles | sort | uniq -u
rm $foundfiles

Upvotes: 2

Views: 2618

Answers (6)

Keeper Hood
Keeper Hood

Reputation: 594

I use this script and it works for me

#!/bin/bash
fileslist="$1"
found="Found:"
notfound="Not found:"
len=`cat $1 | wc -l`
n=0;

while read fn
do
  # don't worry about this, i use it to display the file list progress
  n=$((n + 1))
  echo -en  "\rLooking $(echo "scale=0; $n * 100 / $len" | bc)% "
  if [ $(find / -name $fn | wc -l) -gt 0 ]
  then
    found=$(printf "$found\n\t$fn")
  else
    notfound=$(printf "$notfound\n\t$fn")
  fi
done < $fileslist

printf "\n$found\n$notfound\n"

The line counts the number of lines and if its greater than 0 the find was a success. This searches everything on the hdd. You could replace / with . for just the current directory.

$(find / -name $fn | wc -l) -gt 0

Then i simply run it with the files in the files list being separated by newline

./search.sh files.list 

Upvotes: 0

Dennis Williamson
Dennis Williamson

Reputation: 360035

Give this a try:

find -type f -print0 | grep -Fzxvf - requiredfiles.txt

The -print0 and -z protect against filenames which contain newlines. If your utilities don't have these options and your filenames don't contain newlines, you should be OK.

Upvotes: 1

Michael Krelin - hacker
Michael Krelin - hacker

Reputation: 143081

Try replacing body with [[ -z "$(find . -type f -name $fn)" ]] && echo $fn. (note that this code is bound to have problems with filenames containing spaces).

More efficient bashism:

diff <(sort $fileslist|uniq) <(find . -type f -printf %f\\n|sort|uniq)

I think you can handle diff output.

Upvotes: 1

Almo
Almo

Reputation: 15861

Here is test.bash:

#!/bin/bash

fn=test.bash

exists=`find . -type f -name $fn`
if [ -n "$exists" ]
then
  echo Found it
fi

It sets $exists = to the result of the find. the if -n checks if the result is not null.

Upvotes: 1

tripleee
tripleee

Reputation: 189377

The repeated find to filter one file at a time is very expensive. If your file list is directly compatible with the output from find, run a single find and remove any matches from your list:

find . -type f |
fgrep -vxf - "$1"

If not, maybe you can massage the output from find in the pipeline before the fgrep so that it matches the format in your file; or, conversely, massage the data in your file into find-compatible.

Upvotes: 0

schtever
schtever

Reputation: 3250

#!/bin/bash
fileslist="$1"
while read fn
do
  FPATH=`find . -type f -name $fn`
  if [ "$FPATH." = "." ]
  then
   echo $fn
  fi
done < $fileslist

You were close!

Upvotes: 1

Related Questions