1

The bash script gets arguments, sort, modify and output them in the file. I also try to save the last sorted argument in the variable, but it does not work. The variable is empty. The assignment of the variable is within piped "while loop" that within curly braces.

I have tried introduce the variable at begin of the script, it has no effect.

#!/bin/bash

# Set work dir to place where the script located
cd "$(dirname "$0")"

# Read args
for arg in "$@"
do    
    echo "$arg"
done | sort | { 
while read -r line 
do  
    echo "$line" + "modifier"
    last_sorted_arg="$line" # It does not work
done } > sorted_modified_args.txt


# Empty string - not Ok
echo "$last_sorted_arg"

sleep 3

I can use a temporary file and two loops to work around it, but it looks not so good. Is there a way to do it without a temporary file and two loops?

#!/bin/bash

cd "$(dirname "$0")"

for arg in "$@"
do    
    echo "$arg"
done | sort > sorted_args.txt


while read -r line 
do  
    last_sorted_arg="$line"
done < sorted_args.txt

# Ok
echo "$last_sorted_arg"


# It works too
while read -r line 
do  
    echo "$line" + "modifier"
done < sorted_args.txt > sorted_modified_args.txt

sleep 3
KeyKi
  • 2,693
  • 3
  • 12
  • 24
  • 1
    This is [BashFAQ/024](https://mywiki.wooledge.org/BashFAQ/024). – Benjamin W. May 09 '19 at 15:50
  • The other comments/answers are on-target. ALSO there is no reason in the code you have shown, to surround the while loop with `{ }` pair. Good luck. – shellter May 09 '19 at 16:12
  • The pipe creates a subshell; using `{...}` doesn't create an *additional* subshell, but it doesn't "undo" the pipe-induced shell. – chepner May 09 '19 at 16:45
  • You are also just missing the required semicolon/newline between `}` and `done`. – chepner May 09 '19 at 16:46

1 Answers1

1

The local variable gets lost in the subprocesses.

EDIT: Removed not-working code, trying to get things working close to the original code.

The sorting can be done differently:

#!/bin/bash

last_sorted_arg=$( printf "%s\n" "$@" | sort -n | tee sorted_modified_args.txt | tail -1)
echo "last=${last_sorted_arg}"
Walter A
  • 19,067
  • 2
  • 23
  • 43
  • The first code snippet does not work with git-bash on Windows 10, [`chmod +x foo.sh`](https://stackoverflow.com/a/36147054/11468937) does not help in my case. The sorting code snippet works well. – KeyKi May 09 '19 at 16:57
  • I din't know why the first code didn't work, perhaps in view of git-bash, but the second code snippet was better. So I removed the first. – Walter A May 09 '19 at 19:01
  • Thanks for useful for me the example. Does `tee` can write the modified data (`"$line" + "modifier"`) to sorted_**modified**_args.txt and pipe out the unmodified ones? If no, change the name of the file. – KeyKi May 10 '19 at 11:38
  • I missed the "modifier". Yu can do something like `last_sorted_arg=$( printf "%s modified\n" "$@" | sort -n | tee sorted_modified_args.txt | sed -n '$ s/ .*//p'`. – Walter A May 10 '19 at 12:55