2
alias isbashrcmodf='cmp -s "/home/user/.experimental/bc/$(ls /home/user/.experimental/bc -Art | tail -n 1)" "/home/user/.bashrc"'
alias bashrcbak='cp ~/.bashrc ~/.experimental/bc/.bashrc$(date +-%y-%m-%d-%H-%M-%S-%s)'
if isbashrcmodf; then
    cd $PWD
else
    bashrcbak; echo ".bashrc backed, good to go."
fi

The above script checks the folder /home/user/.expiremental/bc/ for the last modified file (which is previous backup of my .bashrc) and if the present .bashrc is different, a backup is made

I possibly want to avoid the if .. then part and only have if .. else segment. The cd $PWD is a hack way of doing nothing which I used since I couldn't find any better doing nothing command.

EDIT :

I just read somewhere a detailed article on how dangerous it is to parse ls output and rely on ls, it went on saying that it is safer to use glob along ls so instead of ls /home/user/.experimental/bc -Art | tail -n 1 it should be : ls /home/user/.experimental/bc/.bashrc-* -Art | tail -n 1

himanshuxd
  • 348
  • 5
  • 16
  • "if .. then part and only have if .. else segment." what do you mean by that? Cuz that's how bash does if constructs. – Rinzwind Nov 27 '17 at 17:31
  • @Rinzwind I actually tried using `if .. then` with `!$isbashrcmodf` didn't work so any better bash construct you know of that could be used ? Give me examples too, I'm a very slow and dumb learner. – himanshuxd Nov 27 '17 at 17:34

2 Answers2

1

You can use the conditional 'OR' operator || and group your dependent commands inside curly braces so they're executed together, though each command must have a trailing ;:

alias isbashrcmodf='cmp -s "/home/user/experimental/bc/$(ls /home/user/experimental/bc -Art | tail -n 1)" "/home/user/.bashrc"'
alias bashrcbak='cp ~/.bashrc ~/.experimental/bc/.bashrc$(date +-%y-%m-%d-%H-%M-%S-%s)'

isbashrcmodf || { bashrcbak ; echo ".bashrc backed, good to go."; }

A further improvement may be to use the 'AND' conditional operator && to only echo if the bashrcbak command is successful:

isbashrcmodf || { bashrcbak && echo ".bashrc backed, good to go."; }
Arronical
  • 19,653
  • 18
  • 73
  • 128
  • I don't know what `cd $PWD` did in OP's script, but it doesn't appear in yours. – dessert Nov 27 '17 at 17:34
  • @dessert `cd $PWD` was my hack way of _doing nothing_ in the `then` part of script since I'm too lazy to search about and `learn if .. then .. else`. – himanshuxd Nov 27 '17 at 17:38
  • @Arronical Is using `$(ls /home/user/experimental/bc -Art | tail -n 1)` safe for getting last modified file _or_ can that be improved too ? – himanshuxd Nov 27 '17 at 17:41
  • @Hannibal :D I like that approach! – dessert Nov 27 '17 at 17:46
  • @Hannibal Next time you need a shell command that does nothing at all, I recommend using the `:` builtin, which exists for that purpose. For details, run `help :` in `bash`, or check out [`:`'s its documentation in POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_16_01). See also [What is the purpose of the : (colon) GNU Bash builtin?](https://stackoverflow.com/questions/3224878/what-is-the-purpose-of-the-colon-gnu-bash-builtin) – Eliah Kagan Nov 27 '17 at 23:03
1
  1. Use the NOT operator ! when you want to reverse an if statement.

    if ! isbashrcmodf; then
    
  2. Use the AND operator && when you want to run a command only if the last command succeeded.

    bashrcbak && echo ".bashrc backed up, good to go."
    
  3. Don't bother reversing ls sort.

    ls ... -At | head -1
    
  4. Specify which files ls should look at, with a glob.

    ~/.experimental/bc/.bashrc-*
    
  5. Use tildes and vars.

    dir=~/.experimental/bc
    bak_prev="$dir/$(ls "$dir"/.bashrc-* -At | head -1)"
    cmp -s "$bak_prev" ~/.bashrc
    

    and

    bak_next="$dir/.bashrc-$(date +%y-%m-%d-%H-%M-%S-%s)"
    cp ~/.bashrc "$bak_next"
    

    This is partly a matter of personal taste, but it also makes it so that if you want to change the backup dir (for example), you only have to modify one line of code, where $dir is set.

  6. Don't use aliases when you should use functions. Aliases are meant to be used only in interactive sessions, mostly for commands you often run with a certain set of arguments. E.g. alias ls='ls --color=yes'.

    isbashrcmodf(){
        local bak_prev="$dir/$(ls "$dir"/.bashrc-* -At | head -1)"
        cmp -s "$bak_prev" ~/.bashrc
    }
    
    bashrcbak(){
        local bak_next="$dir/.bashrc-$(date +%y-%m-%d-%H-%M-%S-%s)"
        cp ~/.bashrc "$bak_next"
    }
    

    Although in this case, the functions/aliases are only used once, so I wouldn't even bother, unless there is more to the script you didn't include.

  7. Pay very close attention to filenames.

    experimental (typo in the script)

    .expiremental (typo in the question)

In full:

dir=~/.experimental/bc
bak_prev="$dir/$(ls "$dir"/.bashrc-* -At | head -1)"
if ! cmp -s "$bak_prev" ~/.bashrc; then
    bak_next="$dir/.bashrc-$(date +%y-%m-%d-%H-%M-%S-%s)"
    cp ~/.bashrc "$bak_next" &&
        echo ".bashrc backed up, good to go."
fi
wjandrea
  • 14,109
  • 4
  • 48
  • 98
  • I corrected the typo, thanks for pointing out, and +1 for telling me using `function` is better than using `alias`. – himanshuxd Nov 29 '17 at 03:38
  • I'm replacing my aliases with function, can you point out why they are better ? – himanshuxd Nov 29 '17 at 03:39
  • @Hannibal In this case, mostly because it's a good habit. Aliases are very inflexible compared to functions. If you wanted to do anything more complex than this (like handling arguments/options), you would need to use functions anyway. – wjandrea Nov 29 '17 at 04:16
  • 1
    @Hannibal For more details, see [alias vs. function in bash scripts](https://askubuntu.com/q/163882/301745) and [In Bash, when to alias, when to script, and when to write a function?](https://unix.stackexchange.com/q/30925/117037). – wjandrea Nov 29 '17 at 04:19
  • read both of the Qs but answers are imho expansion of your 2nd comment, so I thought of asking you I could : `alias dodis='cp /blah/blah2/x /blah/blah2/x.bak; echo "didit"'` _or_ `dodis() { cp /blah/blah2/x /blah/blah2/x.bak; echo "didit" }` which of these is faster ? – himanshuxd Nov 29 '17 at 07:21
  • @Hannibal They should be about as fast, but you should use the function, especially where the code contains two commands. Btw, using `cp -v` may be better than echoing a confirmation. – wjandrea Nov 29 '17 at 16:57
  • yup using `function`'s – himanshuxd Nov 29 '17 at 17:08