Script to list files not present in audio.txt file

I am having following folder structure.

/root/audios/pop
/root/audios/jazz
/root/audios/rock

Inside those pop, jazz, rock folders there are following files,
p1.ul, p2.ul, p3.ul, j1.ul, j2.ul, j3.ul, r1.ul, r2.ul, r3.ul

And I have a file named as "audio.txt" in the path /root/audios, which is having the following contents,
p1.ul
p2.ul
j1.ul
j2.ul
r1.ul
r2.ul

I have the following script named as script1.sh to check and display all the files present inside the folders when I pass "audio.txt" as a parameter.

#! /bin/sh
var = `cat $1`
for i in $var; do
find . -name "$i" -exec echo "$i" \;
end

$bash script1.sh audio.txt

Could you please modify the code for displaying the files that are not present.
i.e. it should display
p3.ul
j3.ul
r3.ul

Thanks in advance.

I don't thinjk the script you gave us will work. At all. However try this to find those missing:

#! /bin/sh                          

while read i 
do                  
  for j in p1.ul p2.ul j1.ul j2.ul r1.ul r2.ul  
  do
     [ ! -f ${i}/${j} ]  && echo "${i}/${j} is missing"   
  done
done < /root/audios/audio.txt
end     

But hereyou have used

Instead of hardcoding the filenames, is it possible to read them one by one from audio.txt and loop rather? Because there are many more files then I mentioned and its hard to hardcode each one of them..

The following (untested) may be sufficient for your needs:

find /root/audios -type f -name '*.ul' | grep -vFf /root/audios/audio.txt

Regards,
Alister

My bad, I framed the question little wrongly. I need the reverse scenario.

And little correction below as well,

Inside those pop, jazz, rock folders there are following files,
p1.ul, p2.ul, j1.ul, j2.ul, r1.ul, r2.ul

And I have a file named as "audio.txt" in the path /root/audios, which is having the following contents,
p1.ul
p2.ul
p3.ul
j1.ul
j2.ul
j3.ul
r1.ul
r2.ul
r3.ul

So I need to display p3.ul, j3.ul, r3.ul from audio.txt file which are not present in the those folders.

Thanks !

If your shell supports process substitution:

grep -vFf <(find /root/audios -type f -name '*.ul' | sed 's/.*\///') /root/audios/audio.txt

Alternatively, you can use a temporary file:

ul_found=$TMPDIR/ul_found
find /root/audios -type f -name '*.ul' | sed 's/.*\///' > "$ul_found"
grep -vFf "$ul_found" /root/audios/audio.txt
rm "$ul_found"

If you intend to run multiple instances of the temp file version, you'll need a more robust scheme (using mktemp would be much better).

Another approach would be to take a sorted list of the basenames of the pathnames generated by find and use comm(1) to compare it against a sorted audio.txt.

Regards,
Alister

Try this:

find /root/audios -name "*.ul" -exec basename {} \; > Found_Files.txt
egrep -v -f Found_Files.txt audio.txt
 
grep -vFf <(find /root/audios -type f -name '*.ul' | sed 's/.*\///') /root/audios/audio.txt

Both the above approaches of code are giving audio file names which are present from audio.txt in those paths. But I want those not present in those paths.

Did you test our solution?

By the way, the "-v" option in the "egrep" means strings that do NOT match.

Yes I tested it. Instead of displaying p3.ul, j3.ul, r3.ul alone from audio.txt file, it is displaying all the file names present in audio.txt
p1.ul
p2.ul
p3.ul
j1.ul
j2.ul
j3.ul
r1.ul
r2.ul
r3.ul

Sir, I just tested it again!

My the solution does work.

Ok thank you ! I will try again :slight_smile: