How to compare the output of two ls in linux

So, here is a problem that I cannot solve. I have a directory with .h files and a directory with .i files that have the same names as the .h files. I want by simply typing the command so that all .h files that were not found as .i files. This is not a difficult problem, I can do it in some programming language, but I'm just wondering how it will look in cmd :). To be more specific here, this is algo:

  • get file names without extensions from ls * .h
  • get file names without extensions from ls * .i
  • compare them
  • print all names from 1 that are not executed in 2

Good luck

+4
source share
4 answers
diff \ <(ls dir.with.h | sed 's/\.h$//') \ <(ls dir.with.i | sed 's/\.i$//') \ | grep '$<' \ | cut -c3- 

diff <(ls dir.with.h | sed 's/\.h$//') <(ls dir.with.i | sed 's/\.i$//') does ls in two directories, disables extensions and compares two lists. Then grep '$<' finds files that are only in the first listing, and cut -c3- disables the "< " characters that are inserted by diff .

+4
source
 ls ./dir_h/*.h | sed -r -n 's:.*dir_h/([^.]*).h$:dir_i/\1.i:p' | xargs ls 2>&1 | \ grep "No such file or directory" | awk '{print $4}' | sed -n -r 's:dir_i/([^:]*).*:dir_h/\1:p' 
0
source
 ls -1 dir1/*.hh dir2/*.ii | awk -F"/" '{print $NF}' |awk -F"." '{a[$1]++;b[$0]}END{for(i in a)if(a[i]==1 && b[i".hh"]) print i}' 

explanation:

 ls -1 dir1/*.hh dir2/*.ii 

all the * .hh and * .ii files in both directories are listed above.

 awk -F"/" '{print $NF}' 

the above will just print the file name, excluding the full path to the file.

 awk -F"." '{a[$1]++;b[$0]}END{for(i in a)if(a[i]==1 && b[i".hh"]) print i}' 

above will create two associative arrays, one with the file name and one with the exception of the extension. if both hh and ii files exist, the value in the associated array will be 2, if there is only one file, then the value will be 1. So we need an array element whose value is 1, and this must be a header file (.hh) . this can be verified using asso..array b, which is executed in the END block.

0
source

Assuming bash is your shell:

 for file in $( ls dir_with_h/*.h ); do name=${file%\.h}; # trim trailing ".h" file extension name=${name#dir_with_h/}; # trim leading folder name if [ ! -e dir_with_i/${name}.i ]; then echo ${name}; fi done 

Undoubtedly, this can be ported to almost all other shells. I find this less mysterious than some other approaches (although this is certainly my problem), but this is a bit of verbosity. As such. a shell script can help remember it.

0
source

All Articles