I'm writing a script to get a list of only the commands from my crontab. My input data so far looks like this:
$ crontab -l | grep -i --color -v '^#' | awk '$0 ~ /^*\/[0-9]{1,20}|\* /'
*/5 * * * * /usr/local/bin/bash msmtp-queue -r
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
Outcome
Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'
msmtp-queue -r
offlineimap-fetch
checkMail
lbdb-fetchaddress-daily
rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
Tried
I tried starting from the end of file ($NF) and printing everything up until the first forward slash but I just got syntax errors with where to put the brackets:
$ crontab -l | grep -i --color -v '^#' | \
awk -F'/' '{ if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }'
awk: cmd. line:1: { if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }
awk: cmd. line:1: ^ syntax error
How can this be achieved?
CodePudding user response:
If you don't really want the output in your question and instead want the output shown in the currently accepted answer then all you need is:
$ sed -E 's/([^ ]* ){5}//' file
/usr/local/bin/bash msmtp-queue -r
/usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
/usr/bin/env bash ~/bin/checkMail
/usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
The above requires a sed that has -E
to enable EREs, e.g. GNU or BSD sed. With any POSIX sed you could do sed 's/\([^ ]* \)\{5\}//' file
instead or with any POSIX awk awk '{sub(/([^ ]* ){5}/,"")}1' file
.
CodePudding user response:
If you want to
Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'
and given the format of the examples, you can split on the different patterns and check if there are at least 2 parts.
If file
contains the example data:
awk '
{
n = split($0,a, /(^\* \*\/3 \* \* \*|\/usr\/local\/bin\/bash|\/usr\/bin\/env[[:space:]] bash)[[:space:]] /)
if (n > 1) {
print a[2]
}
}
' file
Output
msmtp-queue -r
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
CodePudding user response:
get a list of only the commands from my crontab
I would just jettison 5 first fields, let file.txt
content be
*/5 * * * * /usr/local/bin/bash msmtp-queue -r
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo
then
awk 'BEGIN{FS="[ ]"}{$1=$2=$3=$4=$5="";sub(/^ */,"");print}' file.txt
gives output
/usr/local/bin/bash msmtp-queue -r
/usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
/usr/bin/env bash ~/bin/checkMail
/usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo
Explanation: I inform GNU AWK
that field separator (FS
) and output field separator (OFS
) is single space. I do not use default FS as it would cause changing tab characters to space characters to space and compressing spaces (2 or more consecutive spaces into single space). For each line I set 1st, 2nd, 3rd, 4th and 5th field to empty string, then use sub
to shave off leading spaces, then print
such altered line.
(tested in GNU Awk 5.0.1)
CodePudding user response:
Using sed
(if applicable)
$ sed s'/.*\(bin\/\|\/env \)\?bash \|.*\* //' input_file
msmtp-queue -r
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f- index.lock --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
CodePudding user response:
$ awk -F"bash|env bash|env" '!/^#/ {print $2}' <(crontab -l)
msmtp-queue -r
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log