shell script to display app version number - shell

I am trying to get the application version using the below command
#!/bin/sh
appVersion=$(ssh username#server find '/dir1/dir2/dir3' -type f -name "file.json" -exec grep "version" {} \;| awk -F ': ' '{print $2}' | sed 's/\"//g')
echo $appVersion
Unfortunately am getting the below exception
find: missing argument to `-exec'
Please help me to resolve this issue.

Run the below script, which will behave as expected.
When you run command over ssh, you should use single quote for the multiple commands
#!/bin/sh
appVersion=$(ssh username#server 'find '/dir1/dir2/dir3' -type f -name "file.json" -exec grep "version" {} \;| awk -F ': ' '{print $2}' | sed 's/\"//g'')
echo $appVersion
Refer this link for further details

Related

How to apply my sed command on the files resulting from grep filtering only

I have crafted this sed command which looks to be working fine, only it's being applied to all the files in my directory :
find . -type f -name '*.js' -not -path './node_modules/*' -exec sed -i .bak -E '
1i\
const env = require('\''env-var'\'');
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+) \|\| ([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'').default('\''\3'\'')\4/g
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'')\3/g
' {} \;
I wish to apply those transformations only to the files which match this grep command :
grep -r "process\.env\." --exclude-dir=node_modules
I tried using the pipe but I can't make the two working together. What's the right way to handle it?
EDIT: I tried this
➜ app-service git:(chore/adding-env-example) ✗ grep -r "process\.env\." --exclude-dir=node_modules | sed -i .bak -E '
1i\
const env = require('\''env-var'\'');
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+) \|\| ([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'').default('\''\3'\'')\4/g
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'')\3/g
' {} \;
sed: {}: No such file or directory
I want only the files containing process.env.SOMETHING to be edited.
Work with pipes. xargs comes handy:
find ... -print |
xargs -d '\n' grep -l 'regex' |
xargs -d '\n' sed 'stuff'
xargs: illegal option -- d
You can:
install GNU xargs
install GNU parallel
write a bash loop to read the files line by line, see https://mywiki.wooledge.org/BashFAQ/001
make sure your files do not have spaces or tabs or newlines in filnames and just remove -d '\n' option.
Suggesting to reverse order of commands. sed on filtered list of files.
Files filter is combination of grep filter on find filter: grep -l "process\.env\." $(find . -type f -name '*.js' -not -path './node_modules/*').
sed -i .bak -E '
1i\
const env = require('\''env-var'\'');
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+) \|\| ([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'').default('\''\3'\'')\4/g
s/(^|[^[:alnum:]_])process\.env\.([[:alnum:]_]+)($|[^[:alnum:]_])/\1env.get('\''\2'\'')\3/g
' $(grep -l "process\.env\." $(find . -type f -name '*.js' -not -path './node_modules/*'))

Unable to run a command that contains single quotes through ssh

I can the following command on a machine (let's call it machine A).
find /foo/bar -name "*" -type f -exec md5sum {} + | awk '{print $1}' | sort
This command lists the md5s of the files under /foo/bar.
However, when I append this command into an ssh command
ssh -i ~/.ssh/my_key my_user#123.123.123.123 'find /foo/bar -name "*" -type f -exec md5sum {} + | awk '{print $1}' | sort'
It generates the following error
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
123.123.123.123 is the IP address of machine A. The ssh command is run from another machine.
Is it possible to append the command into the ssh command?
I've tried the following command, it doesn't work, either.
ssh -i ~/.ssh/my_key my_user#123.123.123.123 'find /foo/bar -name "*" -type f -exec md5sum {} + | awk \'{print $1}\' | sort'
The single quote after awk terminates the opening single quote before find.
In your case, there is no parameter expansion being done in your command. Hence the easiest would be to use double quotes for the ssh command.
ssh -i ~/.ssh/my_key my_user#123.123.123.123 "find /foo/bar -name '*' -type f -exec md5sum {} + | awk '{print $1}' | sort"
An alternative would be to replace each ' around the awk argument by '"'"', but this is awkward to read.
Single quotes cannot appear (even escaped) inside a single-quoted string. But they can appear (properly escaped) in an ANSI-quoted string.
ssh -i ~/.ssh/my_key my_user#123.123.123.123 \
$'find /foo/bar -name "*" -type f -exec md5sum {} + | awk \'{print $1}\' | sort'

unable to execute command with find statement in solaris

the script is running normally on ubuntu Linux and i can call bin_packing.awk, but when I try to run it on unix solaris I'm getting an error:
find: bad option -printf
find: [-H | -L] path-list predicate-list
awk: syntax error near line 1
awk: bailing out near line 1
this is the script that works on ubuntu
$ find . -type f -iname '*pdf' -printf "%s %p\n" \
| awk -v c=100000 -f bin_packing.awk
i have tried this and it works but without | awk...part
$ find . -type f -name '*.pdf' -print | perl -lne '$,=" "; #s=stat $_; print $s[7],$_' \
| awk -v c=100000 -f bin_packing.awk
On modern systems, you can use GNU stat or GNU find to extract size without needing to do something awful like parse ls.
Unfortunately, you're not on a modern system, so it's time to do something awful. Fortunately, size is one of the fields of ls that can be semi-reliably parsed (when running it over only one file at a time) as long as you're on a platform that doesn't allow crazy things like usernames with spaces.
find . -type f -iname '*.pdf' -exec bash -c '
for name; do
read -r _ _ _ _ size _ < <(ls -l -- "$name")
printf "%s %s\n" "$size" "$name"
done
' _ {} + | awk -v c=100000 -f bin_packing.awk
If -exec ... {} + syntax doesn't work, you can change the + to a \; to make this slower but more compatible.
If you have the current version of Solaris you can use find's -print option. For older Solaris, use gfind (for GNU find).

How to use "grep" command to list all the files executable by user in current directory?

my command was this
ls -l|grep "\-[r,-][w,-]x*"|tr -s " " | cut -d" " -f9
but for the result I get all the files, not only the ones for which user has a right to execute ( the first x bit is set on).
I'm running linux ubuntu
You can use find with the -perm option:
find . -maxdepth 1 -type f -perm -u+x
OK -- if you MUST use grep:
ls -l | grep '^[^d]..[sx]' | awk '{ print $9 }'
Don't use grep. If you want to know if a file is executable, use test -x. To check all files in the current directory, use find or a for loop:
for f in *; do test -f "$f" -a -x "$f" && echo "$f"; done
or
find . -maxdepth 1 -type f -exec test -x {} \; -print
Use awk with match
ls -l|awk 'match($1,/^...x/) {print $9}'
match($1,/^...x/): match first field for the regular expression ^...x, ie search for owner permission ending in x.

find command using ssh

The below example shows the way how I need the file search and output type which works well in local find.
> find /DBBACKMEUP/ -not -name "localhost*" -type f -name "*2012-10-26*" -exec du -b {} \; | awk '{print $2 "\t" $1}' | awk -F'/' '{print $NF}'
monitor_2012-10-26_22h00m.11.29.135.Friday.sql.gz 119601
test_2012-10-26_22h00m.10.135.Friday.sql.gz 530
status_2012-10-26_22h00m.1.29.135.Friday.sql.gz 944
But I need to print the same command on many servers. So I have planned to exec like this.
>ssh root#192.168.87.80 "find /DBBACKMEUP/ -not -name "localhost*" -type f -name "*2012-10-26*" -exec du -b {} \; | awk '{print $2 "\t" $1}' | awk -F'/' '{print $NF}'"
Ofcourse this gives be a blank output. Any way to parse such a search string in shell and get the output that I desire by ssh?
Thanks!!
Looks like your ssh command there has lots of quotes and double-quotes, which may be the root of your problem (no pun intended). I'd recommend that you create a shell script that will run the find command you desire, them place a copy of it on each server. After that, simply use ssh to execute that shell script instead of trying to pass in a complex command.
Edit:
I think I misunderstood; please correct me if I'm wrong. Are you looking for a way to create a loop that will run the command on a range of IP addresses? If so, here's a recommendation - create a shell script like this:
#!/bin/bash
for ((C=0; C<255; C++)) ; do
for ((D=0; D<255; D++)) ; do
IP="192.168.$C.$D"
ssh root#$IP "find /DBBACKMEUP/ -not -name "localhost*" -type f -name "*2012-10-26*" -exec du -b {} \; | awk '{print "\$"2 \"\\t\" "\$"1}' | awk -F'/' '{print "\$"NF}'"
done
done
Each server?? That must be 749 servers - Your option goes good for hardworkers.. my approach goes good for lazy goose ;) Just a trial did the click ;)
ssh root#192.168.47.203 "find /DBBACKMEUP/ -not -name "localhost*" -type f -name "*2012-10-26*" -exec du -b {} \; | awk '{print "\$"2 \"\\t\" "\$"1}' | awk -F'/' '{print "\$"NF}'"
Tel_Avaya_Log_2012-10-26_22h00m.105.23.Friday.sql.gz 2119
test_2012-10-26_22h00m.10.25.Friday.sql.gz 529
OBD_2012-10-26_22h00m.103.2.203.Friday.sql.gz 914

Resources