0

I am trying to concat "comnp.dat_CY*" files into one file. File name, source path and destination path are the parameters. I am trying to find the last character in the path to check if it is "/" or not. But when I try to do that I am getting error. Below is my script

if [ "$#" -ne 3 ]; then
    echo "Script requires 3 inputs"
    echo "1. File pattern (comnp.dat_CY)"
    echo "2. Source path"
    echo "3. Destination path"
    exit
fi

last_char1 = `echo $2|awk -F  '{if (NF>1) {print $NF}}`
last_char2 = `echo $3|awk -F  '{if (NF>1) {print $NF}}`

if [ $last_char1 != "/" ];then
    ap_src_path = "$2/"
fi
if [ $last_char2 != "/" ];then
    ap_dest_path = "$3/"
fi

cat $ap_src_path$1* > $ap_dest_pathcomnp.dat

Below are my errors:

comnp.sh: Broken pipe
comnp.sh[14]: last_char1:  not found
comnp.sh[15]: last_char2:  not found
comnp.sh[17]: test: argument expected
comnp.sh[20]: test: argument expected

What is wrong in my script?

I am using ksh AIX

4 Answers 4

3

Variable assignment in shell syntax is not allowed to have spaces. last_char = ... is a command called last_char with the arguments = and ..... last_char=... is an assignment that stores ... in the shell variable last_char.


This is a much more efficient and direct way to do what you want:

case $2 in
  */) ap_src_path=$2;; 
  *) ap_src_path=$2/;;
esac
case $3 in
  */) ap_dest_path=$3;;
  *) ap_dest_path=$3/;;
esac

You don't need to extract the last character to do a simple comparison. Also, command substitution is inefficient and clunky for simple shell variable manipulation like this.


More importantly, you don't need to do any of this at all. For the most part, Unix path resolution does not care about duplicated slashes, so path///to//a/file is just as valid as path/to/a/file. In scripts, you can take advantage of this by simply not worrying about duplicate /. In other words you can replace the entire script with

if [ $# -ne 3 ]; then
   # ... same as above ...
fi
pattern=$1
ap_src_path=$2
ap_dst_path=$3

cat "$ap_src_path/$pattern"* > "$ap_dest_path/compn.dat"
2

The problem here is that you cannot use space around =. The shell is very picky about that. And awk commands are totally buggy.

Moreover, in 2014 better use $( ) than backticks. So awk lines should be :

last_char1=$(echo "$2" | awk '{print $NF}' FS='')
last_char2=$(echo "$3" | awk '{print $NF}' FS='')

check http://mywiki.wooledge.org/BashFAQ/082

1
  • I have tried your solution and i am getting the output what i required but when i pass the path without / it is showing error like comnp.sh[18]: ap_src_path: not found comnp.sh[21]: ap_dest_path: not found but in this case also it is giving output.what could be the reason
    – Aravind
    Dec 2, 2014 at 16:28
2
last_char1=$(echo ${2:${#2}-1}); 
last_char2=$(echo ${3:${#3}-1}); 

if [[ "$last_char1" != "/" ]]; then 

Tips:

  • Use $(command), instead of old `command`: Reference
  • Use [[ ]], instead of [ ]: Reference
5
  • 2
    If you use bash your command can be shorter last_char1=${2: -1})(do not miss space between : and -)
    – Costas
    Dec 2, 2014 at 16:08
  • @Albert I have tried your solution but i am getting error like comnp.sh[9]: ${2:${#2}-1}: bad substitution. I am using ksh AIX
    – Aravind
    Dec 2, 2014 at 16:10
  • 1
    @Aravind Albert's answer assumed you were using bash. If you are using ksh there may be feature differences causing your error. See my answer for something that works in all shells.
    – jw013
    Dec 2, 2014 at 16:11
  • Yes, I assumed bash, sorry ;) By the way @Costas, I knew there was a simpler solution but I didn't remember the space. Nice.
    – Albert
    Dec 2, 2014 at 16:14
  • @Aravind May be for ksh you should calculate position=$((${#2} - 1)) before and use last_char1=${2:${position}:1}
    – Costas
    Dec 2, 2014 at 16:27
2

There are multiple problems with your script. Spaces around = should not be present, single quotes ' are not paired, and additionally awk -F requires a parameter - a field separator, so you should rather write awk -F '' '{if (NF>1) {print $NF}}'.

But in fact if you use any reasonable shell like bash or zsh then you can simply write

cat "${ap_src_path}/${1}*" > "${ap_dest_path}/comnp.dat"

without a need of last characters and all those if conditions. Possible additional / are just ignored, so for example a path /var//log///mysql////mysql.log is perfectly fine syntax.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .