0

What is the right way of assigning the output of lowercase_last2 to another variable? What am I doing wrong below?

I have a shell script test_lowercase_last.sh that defines a couple of functions

#!/bin/bash

function lowercase_last2() (
    PART2=/"${1##*/}"
    PART1=${1%"$PART2"}
    PART2_LOWER=$(echo "$PART2" | tr '[:upper:]' '[:lower:]')
    echo ${PART1}${PART2_LOWER}
)

function basic() (
    echo "Testing"
)

and another script that means to use them

#!/bin/bash
echo $(basic)
echo $(lowercase_last /home/santiago/Test)

But this is what I get

$ source test_lowercase_last.sh
$ ./test_bash_func.sh
./test_bash_func.sh: line 2: basic: command not found

./test_bash_func.sh: line 3: lowercase_last: command not found

I actually mean to assign the output of lowercase_last2 to another variable, but I guess once I get this right, it should be straightforward. Then the question.

6
  • 2
    Sourcing functions into your interactive shell doesn't export them to child processes unless you do that explicitly. Which is good; you wouldn't want interactive-shell customization to be able to break random scripts that you run. Commented Apr 17, 2020 at 15:47
  • 1
    ...so, the right thing is to source the library with the functions in the script that needs those functions. Commented Apr 17, 2020 at 15:48
  • BTW, using a .sh extension on a library that's using deliberately POSIX-noncompliant syntax is misleading at best. function foo() { is merging the legacy-ksh function foo { syntax and the POSIX-compliant foo() { syntax in a way that's not compatible with either legacy ksh or the POSIX specification. Commented Apr 17, 2020 at 15:49
  • ...if you write a shell library that uses bash-only syntax, name it with a .bash extension. Whereas executables (a category including shell scripts as opposed to shell libraries) should have no extension at all; you run pip, not pip.py; and you run ls, not ls.elf. Commented Apr 17, 2020 at 15:50
  • @CharlesDuffy - As for the mixing of legacy-ksh and POSIX, what changes would you suggest I introduce? Commented Apr 17, 2020 at 19:18

1 Answer 1

2

Source the library in the script you use it from:

#!/bin/bash
source test_lowercase_last.sh

echo "$(basic)"
echo "$(lowercase_last /home/santiago/Test)"

Unless you use export -f lowercase_last basic to export your functions to the environment, they are not automatically inherited by separate shells. (Subshells inherit copies of internal state; but those are fork()ed with no exec() call; when you run a new script, it's across an exec boundary, so it doesn't have access to the original process's non-exported variables).


By the way -- see BashPitfalls #14 re: why echo's arguments should always be quoted when non-constant (and, as an aside, the last table in https://wiki.bash-hackers.org/scripting/obsolete discussing function declaration syntax options).

Sign up to request clarification or add additional context in comments.

2 Comments

I actually mean to source test_lowercase_last.sh in .bashrc, so the functions are available in all child processes. So I would add line export -f lowercase_last basic in my script, as you suggested... (I am not certain the export is needed in this case, I will check).
Writing a script that doesn't work on anyone's account but yours, or after a sudo execution that discards environment variables, or after running a non-bash shell that (legally!) discards environment variables that don't translate to valid shell variable names, isn't exactly a principle-of-least-surprise practice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.