How to find directories containing two different file names?

I have a music volume on my NAS which contains plenty of CD's.The file names are typically 01.name.mp3 , 02.name.mp3 etc. On another part of the NAS I store snapshots taken and named at each hour of the day 00-00-00.jpg , 01-00-00.jpg.... 23-00-00.jpg I made a crontab to delete the snapshots before 7am as they were usually dark , so no point in keeping them.

Well guess what , I had a link in snapshots folder which I had forgotten ,pointing to the music files. So after a while I realized most of my music files from 01-name.mp3 to 07-name.jpg had been deleted. What I am trying to do is assess the damage & display only the directories that contain files starting with 09-name.mpg AND do not contain 01-name.mp3.This folder (or cd) has had the files lower than 07 deleted.

Ideally during the search I would like to eliminate any other directory containing a non-numeric name like "main-theme.mp3" as I know these folders are complete.

I did try:

find . -name "09*" -a ! -name "01*"

but it didn't work. I also tried this which did not work

find . -mindepth 2 -maxdepth 2 -type d '!' -exec test -e "{}/01*" ';' -print

My system:

Linux fut-NUC7i3BNH 4.15.0-96-generic #97-Ubuntu SMP Wed Apr 1 03:25:46 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL=""
SUPPORT_URL=""
BUG_REPORT_URL=""
PRIVACY_POLICY_URL=""
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
1

2 Answers

The next command

  • looks for all unique folders containing files starting with 09*
  • looks for all unique folders containing files starting with 01*
  • removes lines which point to 01* files from output which points to 09* files.

Number of 09* files should be bigger then number of 01* files because a part of them have been removed, so the command will output only folders with 01* files removed.

snpath=$(echo ~/test/snapshots/) && \
find $snpath -name "09*" | sed 's|\(.*\)/.*|\1|' | sort | uniq > allf.txt && \
find $snpath -name "01*" | sed 's|\(.*\)/.*|\1|' | sort | uniq > notallf.txt && \
grep -Fvxf notallf.txt allf.txt | grep -oP "^$snpath\K.*"
  • $ snpath=$(echo ~/test/snapshots/) - full path to snapshots folder
  • find $snpath -name "09*" finds all files starting with 09 with their full paths
  • sed 's|\(.*\)/.*|\1|' strips files names leaving parent directories paths only
  • sort | uniq removes duplicate paths lines leaving only unique directories names
  • find $snpath -name "01*" | sed 's|\(.*\)/.*|\1| finds undesired directories we do not want to see (they do not contain removed files)
  • grep -Fvxf notallf.txt allf.txt removes undesired folders names from all folders' list leaving only folders that contain 09* files names and do not contain 01* files names
  • awk 'NR==FNR{a[$0];next} !($0 in a)' notallf.txt allf.txt could be used instead of previous grep command
  • grep -oP "^$snpath\K.*" path to snapshots folder from output

    $ tree ./
    ./
    ├── allf.txt
    ├── Alligator Records 20th Anniversary Collection
    │   ├── CD1
    │   │   ├── 01 - Hound Dog Taylor And The Houserockers .mp3
    │   │   ├── 02 - James Cotton - No Cuttin Loose.mp3
    │   │   ├── 03 - Black Cat Bone .mp3
    │   │   ├── 04 - Professor Longhair - Big Chief.mp3
    │   │   ├── 05 - Koko Taylor - Thats Why Im Crying.mp3
    │   │   ├── 06 - Tinsley Ellis - Double-eyed Whammy.mp3
    │   │   ├── 07 - Lucky Peterson - Im Free.mp3
    │   │   ├── 08 - A.C. Reed-Stevie Ray Vaughan mp3
    │   │   ├── 09 - Little Charlie And The Nightcats - Rain.mp3
    │   │   └── file1
    │   ├── CD2
    │   │   ├── 09 - Bessie Smith,Moan, You Moaners.mp3
    │   │   ├── 10 - Louis Armstrong,Nobody Knows The Trouble Ive Seen.mp3
    │   │   ├── 11 - Golden Gate Quartet,The Valley Of Time.mp3
    │   │   └── 12 - Golden Gate Quartet,The Sun Didnt Shine.mp3
    │   └── file2
    ├── file
    └── notallf.txt
    3 directories, 18 files

Result:

$ snpath=$(echo ~/test/snapshots/) && find $snpath -name "09*" | sed 's|\(.*\)/.*|\1|' | sort | uniq > allf.txt && find $snpath -name "01*" | sed 's|\(.*\)/.*|\1|' | sort | uniq > notallf.txt && grep -Fvxf notallf.txt allf.txt | grep -oP "^$snpath\K.*"
Alligator Records 20th Anniversary Collection/CD2
9

You can do it in two steps: find directories which contain name number one, then find in the output directories which contain name number 2.

Example:

find . -name "09* > output_first_search
cat output_first_search | grep "01*"
2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like