0

I'm trying to write a simple Linux make command with bash scripting. here is what I have written so far:

#!/usr/bin/env bash

function make_cmd()
{
  read target colon sources
  for src in $sources; do
    if [ $src -nt $target ]; then
      while read cmd && [[ $(echo "$cmd" | grep "$(printf '\t')"*) ]]; do
        echo "executing $cmd";
        eval ${cmd#$(printf '\t')};
      done
      break;
    fi
  done
}

this is the format of input:

target.file : source.file
[tab]command

for example:

target.txt : source.txt
    ls
    cd

the script works well but it cannot find commands starting with tab. it always execute them. for example, the commands in this input is still executed.

target.txt : source.txt
ls
cd

how can I fix this?

1

The builtin read command splits words using the value of IFS, which by default contains a space, a tab and a newline. Hence when using read to get the input, the tab is removed.

Begin the function with:

IFS_SAVE="$IFS"
IFS=' '

Now only spaces will separate words. At the end of the function restore IFS to its original value:

IFS="$IFS_SAVE"

Note that you can use a literal tab if escaped by a backslash. Furthermore I would not use grep to match the tab, use builtins where possible as that's faster. My version of the function would be:

function make_cmd()
{
  SAVE_IFS="$IFS"
  IFS=' '
  read target colon sources
  for src in $sources; do
    if [ $src -nt $target ]; then
      while read cmd; do
        case "$cmd" in
          $'\t'*)  echo "executing $cmd"
                eval ${cmd# }
                ;;
          *)    ;;
        esac
      done
      break;
    fi
  done
  IFS="$SAVE_IFS"
}

The $'\t' substitutes a literal tab (thanks to Kusalananda for the tip).

Insert a literal tab after the # in the variable substitution. Using the printf might be more readable though.

| improve this answer | |
  • I added the lines you said to my code, still doesn't work. your code does not execute the cmd no matter how it is entered. – Fatemeh Karimi Dec 5 '19 at 8:59
  • 1
    If you run cat -t filename on your script, does it show the tabs in the code as ^I? E.g. ^I\^I*)^Iecho "executing $cmd". If not, your editor isn't inserting the tabs as-is. – wurtel Dec 5 '19 at 9:50
  • yes your right. it doesn't insert tabs. I will fix this and test everything again – Fatemeh Karimi Dec 5 '19 at 10:08
  • @FatemehKarimi You may also be able to use $'\t'*) in the case statement. – Kusalananda Dec 5 '19 at 10:54
  • @Kusalananda thanks my dear friend. I replaced it with $'\t'*) and it solved my problem. – Fatemeh Karimi Dec 6 '19 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.