Linux - multiple command execution using semicolon - linux

I have a scenario where I need to execute date command and ls -lrth|wc -l command at the same time.
I read somewhere on google that I can do it in the way shown below using the semicolon
ls -lrth | wc -l | ; date
This works super fine!
But the problem is when I want to extract the output of this. This gives a two line output with the output of ls -lrth |wc -l in the first line and the second line has the date output like shown below
$ cat test.txt
39
Mon Oct 26 16:11:20 IST 2015
But it seems like linux is treating these two lines as if its on the same line.
I want this to be formatted to something like this
39,Mon Oct 26 16:11:20 IST 2015
For doing this I am not able to separately access these two lines (not even with tail or head).
Thanks in advance.
EDIT
Why I think linux is treating this as a same line because when I do this as shown below,
$ ls -lrth| wc -l;date | head -1
39
Mon Oct 26 16:24:07 IST 2015
The above reason is for my assumption of the one line thing.

Have you already tried using an echo?
echo $(ls | wc -l) , $(date)
(or something similar, I don't have a Linux emulator here)

If you want in your script
./script.sh
#!/bin/bash
a=$(ls -lrth | wc -l)
b=$(date)
out="$a,$b"
echo "$out"
EDIT
ls -lrth| wc -l;date | head -1
The semicolon simply separates two different commands ";"

Pipe to xargs echo -n (-n means no newline at end):
ls -lrth | wc -l | xargs echo -n ; echo -n ","; date
Testing:
$ ls -lrth | wc -l | xargs echo -n ; echo -n ","; date
11,Mon Oct 26 12:57:14 EET 2015

Related

BASH: How to add text in the same line after command

I have to print number of folders in my directory, so i use
ls -l $1| grep "^d" | wc -l
after that, I would liked to add a text in the same line.
any ideas?
If you don’t want to use a variable to hold the output you can use echo and put your command in $( ) on that echo line.
echo $(ls -l $1| grep "^d" | wc -l ) more text to follow here
Assign the result to a variable, then print the variable on the same line as the directory name.
folders=$(ls -l "$1" | grep "^d" | wc -l)
printf "%s %d\n" "$1" "$folders"
Also, remember to quote your variables, otherwise your script won't work when filenames contain whitespace.

echo $variable in cron not working

Im having trouble printing the result of the following when run by a cron. I have a script name under /usr/local/bin/test
#!/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ARAW=`date +%y%m%d`
NAME=`hostname`
TODAY=`date '+%D %r'`
cd /directory/bar/foo/
VARR=$(ls -lrt /directory/bar/foo/ | tail -1 | awk {'print $8'} | ls -lrt `xargs` | grep something)
echo "Resolve2 Backup" > /home/user/result.txt
echo " " >> /home/user/result.txt
echo "$VARR" >> /home/user/result.txt
mail -s "Result $TODAY" email#email.com < /home/user/result.txt
I configured it in /etc/cron.d/test to run every 1am:
00 1 * * * root /usr/local/bin/test
When Im running it manually in command line
# /usr/local/bin/test
Im getting the complete value. But when I let cron do the work, it never display the part of echo "$VARR" >> /home/user/result.txt
Any ideas?
VARR=$(ls -lrt /directory/bar/foo/ | tail -1 | awk {'print $8'} | ls -lrt `xargs` | grep something)
ls -ltr /path/to/dir will not include the directory in the filename part of the output. Then, you call ls again with this output, and this will look in your current directory, not in /path/to/dir.
In cron, your current directory is likely to be /, and in your manual testing, I bet your current directory is /path/to/dir
Here's another approach to finding the newest file in a directory that emits the full path name:
stat -c '%Y %n' /path/to/dir/* | sort -nr | head -1 | cut -d" " -f 2-
Requires GNU stat, check your man page for the correct invocation for your system.
I think your VARR invocation can be:
latest_dir=$(stat -c '%Y %n' /path/to/dir/* | sort -nr | head -1 | cut -d" " -f 2-)
interesting_files=$(ls -ltr "$latest_dir"/*something*)
Then, no need for a temp file:
{
echo "Resolve2 Backup"
echo
echo "$interesting_files"
} |
mail -s "Result $TODAY" email#email.com
Thanks for all your tips and response. I solved my problem. The problem is the ouput of $8 and $9 in cron. I dont know what special field being read while it is being run in cron. Im just a newbie in scripting so sorry for my bad script =)

How do I find the latest date folder in a directory and then construct the command in a shell script?

I have a directory in which I will have some folders with date format (YYYYMMDD) as shown below -
david#machineX:/database/batch/snapshot$ ls -lt
drwxr-xr-x 2 app kyte 86016 Oct 25 05:19 20141023
drwxr-xr-x 2 app kyte 73728 Oct 18 00:21 20141016
drwxr-xr-x 2 app kyte 73728 Oct 9 22:23 20141009
drwxr-xr-x 2 app kyte 81920 Oct 4 03:11 20141002
Now I need to extract latest date folder from the /database/batch/snapshot directory and then construct the command in my shell script like this -
./file_checker --directory /database/batch/snapshot/20141023/ --regex ".*.data" > shardfile_20141023.log
Below is my shell script -
#!/bin/bash
./file_checker --directory /database/batch/snapshot/20141023/ --regex ".*.data" > shardfile_20141023.log
# now I need to grep shardfile_20141023.log after above command is executed
How do I find the latest date folder and construct above command in a shell script?
Look, this is one of approaches, just grep only folders that have 8 digits:
ls -t1 | grep -P -e "\d{8}" | head -1
Or
ls -t1 | grep -E -e "[0-9]{8}" | head -1
You could try the following in your script:
pushd /database/batch/snapshot
LATESTDATE=`ls -d * | sort -n | tail -1`
popd
./file_checker --directory /database/batch/snapshot/${LATESTDATE}/ --regex ".*.data" > shardfile_${LATESTDATE}.log
See BashFAQ#099 aka "How can I get the newest (or oldest) file from a directory?".
That being said, if you don't care for actual modification time and just want to find the most recent directory based on name you can use an array and globbing (note: the sort order with globbing is subject to LC_COLLATE):
$ find
.
./20141002
./20141009
./20141016
./20141023
$ foo=( * )
$ echo "${foo[${#foo[#]}-1]}"
20141023

Assigning the output of the "at" command in a bash script

I'm trying to capture the results of the "at" command inside a Bash script. The various ways of capturing command output don't seem to work, but I'm not sure if it's the pipe in the command or something else.
echo $cmd | at $deployat
produces the output
job 42 at 2014-04-03 12:00
And I'm trying to get at the time the job was set for.
However, I expected something like
v=$($cmd | at $deployat)
echo $v
Would work, or
v=$(echo $cmd | at $deployat)
echo $v
Or
v=`$cmd | at $deployat`
echo $v
But all of those leave the script hung, looking like it's waiting for some input.
What is the proper way to do this to end up with a variable like:
2014-04-03 12:00
============================
Edit:
One possible complication is that the $cmd has flags with it:
ls -l
for example.
The expanded command could be something like:
echo ls -l | at noon tomorrow
Solution:
v=$(echo $cmd | at $deployat 2>&1)
echo $v
at prints its output to stderr not stdout. Use 2>&1 to pipe the stderr of at into stdout. Example:
~$ out=$(echo cat Hello | at -v 2014-04-03 2>&1 | head -n 1)
~$ echo $out
Thu Apr 3 01:21:00 2014
With -v it prints the execution time on the first line which is taken by head -n 1.

BASH script : Integrated document creation hangs

I find that a piece of my bash script causes the hang up. I extract it here :
#!/bin/bash
cat << EndOfFspreadFile >> ./myscript.sh
echo Enter Source Path :
read SRCPATH
FILECNT=`find $SRCPATH/* 2>/dev/null | wc -l`
FILECNTERR=`find $SRCPATH/* 2>&1 | grep "find:" | wc -l`
echo count : $FILECNT
echo problems : $FILECNTERR
EndOfFspreadFile
echo done
This script is expected to just append the script part in the integrated block into myscript.sh file. But it just HANGS !
Thanks !
- Mohamed -
Your $ variables and back quotes will get expanded. You need to escape them in script.
Right now you end up searching the entire filesystem.
Basically, find $SRCPATH/* 2>/dev/null | wc -l gets executed as find /* 2>/dev/null | wc -l
Here is how you can rewrite it (just one line example):
FILECNT=\$(find \$SRCPATH/* 2>/dev/null | wc -l)
By the way, it's easy to find out if you run bash -x <your script>.

Resources