Easiest way to check for include - sh

I would like to check for cpp files to contain
#include <stdafx.h>
Since I do not want this thing to fail, when e.g. comments are in front of the include, I would prefer a way of checking, that honors the actual c++ syntax.
Can this be easily done (in a cross-platform way (using cygwin sh on Windows))?

cpp, the C preprocessor from the GNU compiler collection, has an -M flag that lists the files a C file depends on, i.e. the headers it includes. You could run cpp on all your files, then filter out stdafx.h. I don't personally use Cygwin, but I believe something like this should work:
find . -type f -name "*.cpp" -exec sh -c "echo {} && cpp -M {} | grep -c stdafx.h" \;
This finds every file with a name that ends with cpp, then executes a shell that in turn echoes the file name we're looking at. It then runs it through cpp, finally grepping cpp's output for the header we're looking for and counting the lines. The output should look something like this (looking for stdio.h in the Git source tree):
./diff.c
0
./gettext.c
1
./gpg-interface.c
0
./hashmap.c
0
./hex.c
0
./environment.c
0
./remote-testsvn.c
0
./server-info.c
0
./compat/fopen.c
1
./compat/basename.c
1
./compat/strtoimax.c
1
./compat/hstrerror.c
1
./compat/pread.c
1
./compat/gmtime.c
1
./compat/setenv.c
1
Of course, if you only want to check a single file, you don't need the whole find invocation, you can just do "cpp -M myfile.cpp | grep -c stdafx.h" which will give you either a 0 if it's not in there or a 1 if it is.

Related

Autocomplete directories in a subfolder with the Fish shell

I'm having trouble getting the 'complete' function in the fish shell to behave as I would like and I've been searching for an answer for days now.
Summary
Essentially I need to provide tab directory auto-completion as if I was in a different directory to the one I am currently in. It should behave exactly as 'cd' and 'ls' do, but with the starting point in another directory. It seems like such a trivial thing to be able to do but I can't find a way to make it work.
Explanation
Example folder structure below
- root
- foo
- a
- dir1
- subdir1
- dir2
- subdir2
- b
- dir3
- subdir3
- dir4
- subdir4
I am running these scripts whilst in the 'root' directory, but I need tab auto-complete to behave as if I was in the 'foo' directory.
testfunc -d a/dir2/subdir2
Instead of
testfunc -d foo/a/dir2/subdir2
There are a lot of directories inside 'foo' and a lot of sub-directories within them, and this auto-complete behaviour is necessary to speed our process (this script is used extensively throughout the day).
Attempted Solution
I've tried using the 'complete' builtin to get this working by specifying the directory to use, but all this managed to do was auto-complete the first level of directories with a space after the argument instead of continuing to auto-complete like 'cd' would.
complete -x -c testfunc -a "(__fish_complete_directories ./foo/)"
Working bash version
I have already got this working in Bash and I am trying to port it over to fish. See below for the Bash version.
_testfunc()
{
local cur prev words cword
_init_completion || return
compopt +o default
case $prev in
testfunc)
COMPREPLY=( $( compgen -W '-d' -- "$cur" ) )
compopt +o nospace
return
;;
-d)
curdir=$(pwd)
cd foo/ 2>/dev/null && _filedir -d
COMPREPLY=( $( compgen -d -S / -- "$cur" ) )
cd $curdir
return
;;
esac
} &&
complete -o nospace -F _testfunc testfunc
This is essentially stepping into the folder that I want, doing the autocompletion, then stepping back into the original folder that the script was run in. I was hoping this would be easier in Fish after getting it working in Bash (I need to support these two shells), but I'm just pulling my hair out.
Any help would be really appreciated!
I am not a bash completions expert, but it looks like the bash completions are implemented by changing directories, running completions, and then changing back. You can do the same in fish:
function complete_testfunc
set prevdir $PWD
cd foo
__fish_complete_directories
cd $prevdir
end
complete -x -c testfunc -a "(complete_testfunc)"
does that work for you?

ExifTool - check if all files have the same amount of channels

I would need your help with ExifTool. I am trying to check if all of my .wav files have the same amount of channels through meta-data. How should I proceed? Should I print out the tags first and then write a script to check if they are all the same or is there a better way?
Thank you for your help.
You'd have to do it externally (via a file or your shell controls or something.
e.g., in bash:
if [ "$(exiftool -NUMCHANNELS a.wav)" == "$(exiftool -NUMCHANNELS b.wav)" ]
then
echo match
fi
To see if many files all match, you could do something like
exiftool -q -NUMCHANNELS *.wav | uniq | wc -l
And verify the output is 1

How to grep over 1 million files?

I need to grep about 1 million files. If there's a better way to do this, let me know. I was thinking there may be a faster way to do it in perl.
What I'm trying to do is export every line that contains the text httpsfile in it.
Here's what I'm trying to run:
grep 'httpsfile' * >> grepped.txt
Here's the error I'm getting:
-bash: /bin/grep: Argument list too long
Any help would be appreciated.
You can do it in parallel if you want:
ls > /tmp/files
parallel -a /tmp/files --xargs -s 100 grep 'httpsfile'
Unless you have a lot of RAM and your on million files are already in the buffer cache, parallelizing won't be of any help given the fact the operation will be I/O bound so here is the fastest still portable (POSIX) way:
find . -exec grep httpsfile {} + > grepped.txt
Note that unlike the accepted answer solution, using find won't fail with oddly named files. Have a look to https://unix.stackexchange.com/questions/128985/why-not-parse-ls
Try ls | xargs grep httpsfile.
Just change * to ./ or, whatever is the root directory that contains the 1 million files. You might need to add -r as well to make grep recursive and look into nested directories.
* in the shell expands out into all the files.

Utility/Tool to get hash value of a data block in ext3

I have been searching for a utility/tool that can provide the md5sum(or any unique checksum) of a data block inside ext3 inode structure.
The requirement is to verify whether certain data blocks get zeroed, after a particular operation.
I am new to file systems and do not know if any existing tool can do the job, or I need to write this test utility myself.
Thanks...
A colleague provided a very elegant solution. Here is the script.
It needs the name of file as a parameter, and assumes the file system blocksize to be 4K
A further extension of this idea:
If you know the data blocks associated with the file (stat ), you can use 'skip' option of 'dd' command and build small files, each of 1 block size length. Further, you can get the md5sum of these blocks. So, this way you can get md5sum directly from the block device. Not something you would want to do everyday, but a nice analytical trick.
==================================================================================
#!/bin/bash
absname=$1
testdir="/root/test/"
mdfile="md5"
statfile="stat"
blksize=4096
fname=$(basename $absname)
fsize=$( ls -al $absname | cut -d " " -f 5 )
numblk=$(( fsize/blksize ))
x=1
#Create the test directory, if it does not exist already
if [[ ! -d $testdir ]];
then
`mkdir -p $testdir`
fi
#Create multiple files from the test file, each 1 block sized
while [[ $x -le $numblk ]]
do
(( s=x-1 ))
`dd if=$absname of=$testdir$fname$x bs=4096 count=1 skip=$s`
`md5sum $testdir$fname$x >> $testdir$mdfile`
(( x=x+1 ))
done

Need to convert ksh command line to sh

I'm trying to do a simple operation in ksh that I need to repeat in sh (Bourne shell)
All I want to do is append the contents of the first line of hte pay_period.txt file to the end of the new file name. This works great in ksh, but does not work in bourne. The program I'm using defaults to sh and I can't change that. Also I can't have actual shell scipts in the directories. So I have to issue commands.
How can I make the equivalent command below work in bourne
mv HEPAY.txt HE_PAY"$(/usr/bin/head -1 pay_period.txt)."txt
The results of $(/usr/bin/head -1 pay_period.txt) is 20140101.
If you are really talking about a real Bournce shell then you need to use backticks for command substitution ($() is POSIX and portable among "modern", POSIX-compliant shells but won't work in old, legacy shells), e.g.
mv HEPAY.txt HE_PAY`/usr/bin/head -1 pay_period.txt`.txt
Other than that I see no reason why this should not work.
PS: Note that head -1 isn't POSIX-compliant either (head -n 1 is).