2

I am trying to figure out how to setup a script that will do the following:

files in dir:

a_3.txt  
b_3.txt  
c_3.txt

script(s) in dir:

1.sh  # run this for a_*.txt
2.sh  # run this for b_*.txt or c_*.txt

I need to have a function that will select the file and run it through a specified script.

    fname = "c_*.txt" then
    if "${fname}" = "c_*.txt"
    ./1.sh ${fname} [param1] [param2]
fi

or some sorts. the script will be in the same location as the files/scripts it will utilize. in words, the script will run a specified script based on the start of the file name and the filetype/suffix. any help would be appreciated.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Jazzkatt
  • 65
  • 2
  • 8
  • 1
    Take a look at the `case` statement, it's good for selecting different actions based on a variable matching patterns. – Barmar Sep 15 '16 at 18:16
  • BTW, http://shellcheck.net/ is your friend. – Charles Duffy Sep 15 '16 at 18:20
  • Do you mean that `a_*.txt` gets `1.sh`, `b_*.txt` gets `2.sh`, etc? Please be more specific in the question about the desired behavior -- one example isn't good enough to establish a pattern. – Charles Duffy Sep 15 '16 at 18:22
  • Understandable, failing at remembering how to set it in case there are multiple files for a give name - and having it run the script for each file – Jazzkatt Sep 15 '16 at 18:23
  • a_*.txt is ran against 1.sh --- b_*.txt is ran against 1.sh --- and c_*.txt is ran again 2.sh – Jazzkatt Sep 15 '16 at 18:24
  • Please edit your question to specify that clearly. – Charles Duffy Sep 15 '16 at 18:25
  • BTW, if a script is intended to be run as a command rather than sourced as a library, you might want to consider avoiding file extensions. You don't run `ls.elf`, after all -- calling your script just `1`, not `1.sh`, also means you don't falsely imply it can be run with a POSIX sh interpreter rather than bash, and that you don't need to rename it and change all its callers to use the new name if you rewrite it in a different, non-shell language. – Charles Duffy Sep 15 '16 at 18:27
  • BTW, `if foo = bar; then ...` doesn't compare `foo` and `bar` -- it runs `foo` as a command, with its first argument being `=`, and its second argument being `bar`, and decides on which branch of the `if` statement to follow depending on whether that command returns a successful exit status. `foo=bar`, by contrast, assigns the value `bar` to the variable named `foo`. If you want to *compare* `foo` and `bar`, you need to use `test` -- and if `bar` is a glob expression, you need to use the *extended `test` syntax* available with `[[ ]]`. Thus: `if [[ "$fname" = c_*.txt ]]; then` – Charles Duffy Sep 15 '16 at 18:32

1 Answers1

3

Selecting everything and filtering is more trouble than going pattern-by-pattern.

#!/bin/bash
#      ^^^^- bash is needed for nullglob support

shopt -s nullglob # avoid errors when no files match a pattern

for fname in a_*.txt; do
  ./1.sh "$fname" param1 param2 ...
done

for fname in b_*.txt c_*.txt; do
  ./2.sh "$fname" param2 param3 ...
done

That said, if you really want to iterate over all files in the directory, use a case statement:

# this is POSIX-compliant, and will work with #!/bin/sh, not only #!/bin/bash

for fname in *; do # also consider: for fname in [abc]_*.txt; do
  case $fname in
    a_*.txt)         ./1.sh "$fname" param1 param2 ... ;;
    b_*.txt|c_*.txt) ./2.sh "$fname" param1 param2 ... ;;
    *)               : "Skipping $fname" ;; # this will be logged if run with bash -x
  esac
done
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441