当前位置: 动力学知识库 > 问答 > 编程问答 >

linux - Change directory to path of parent/calling script in bash

问题描述:

I have dozens of scripts, all in different directories. (exported/expanded Talend jobs)

At this moment each job has 1 or 2 scripts, starting with the same lines, most important one:

CD ***path-to-script***

and several lines to set the Java path and start the job.

I want to create a script, which will be ran from all these scripts.

e.g.:

/scripts/talend.sh

And in all talend scripts, the first line will run /scripts/talend.sh, some examples of where these scripts are ran from:

/talend-job1_0.1/talend-job1_0.1/talend-job1/talend-job1.sh

/talend-task2_0.1/talend-task2_0.1/talend-task2/talend-task2.sh

/talend-job3_0.1/talend-job3_0.1/talend-job3/talend-job3.sh

How can I determine where the /scripts/talend.sh is started from, so I can CD to that path from within /scripts/talend.sh.

The Talend scripts are not run from within the directory itself, but from a cronjob, or a different users home directory.

EDIT:

The question was marked as duplicate, but Can a Bash script tell what directory it's stored in? is not answering my question 100%.

Problem is:

- The basic script is being called from different scripts

- Those different scripts can be run from command line, with, and with or without a symbolic link.

- The $0, the $BASH_SOURCE and the pwd all do some things, but no solution mentioned covers all the difficulties.

Example:

/scripts/talend.sh

In this script I want to configure the $PATH and $HOME_PATH of Java, and CD to the place where the Talend job is placed. (It's a package, so that script MUST be run from that location).

Paths to the jobs are, for example:

/u/talend/talendjob1/sub../../talendjob1.sh

/u/talend/talendjob2/sub../../talendjob2.sh

/u/talend/talendjob3/sub../../talendjob3.sh

Multiple jobs are run from a TMS application. This application cannot run these scripts with the whol name (to long, name can only be 6 long), so in a different location I have symbolic links:

/u/tms/links/p00001 -> /u/talend/talendjob1/sub../../talendjob1.sh

/u/tms/links/p00002 -> /u/talend/talendjob1/sub../../talendjob2.sh

/u/tms/links/p00003 -> /u/talend/talendjob1/sub../../talendjob3.sh

/u/tms/links/p00004 -> /u/talend/talendjob1/sub../../talendjob4.sh

I think you get an overview of the complexity and why I want only one basic talend script, where I can leave all basic stuff. But I only can do that, if I know the source of the Talend script, because there I have to be to start that talend job.

网友答案:

These answers (beyond the first) are specific to Linux, but should be very robust there -- working with directory names containing spaces, literal newlines, wildcard characters, etc.


To change to your own source directory (a FAQ covered elsewhere):

cd "$(basename "$BASH_SOURCE")"

To change to your parent process's current directory:

cd "/proc/$PPID/cwd"

If you want to change to the directory passed as the first command-line argument to your parent process:

{ IFS= read -r -d '' _ && IFS= read -r -d '' argv1; } <"/proc/$PPID/cmdline"
cd "$argv1"

That said, personally, I'd just export the job directory to the environment variable in the parent process, and read that environment variable in the children. Much, much simpler, more portable, more accurate, and compliant with best process.

网友答案:

You can store pwd in a variable and then cd to it when you want to go back

网友答案:

This works for me:

In

/scripts/talend.sh

do

cd ${1%/*}

${1%/*} will strip off everything after the last / effectively providing a dirname for $1, which is the path to the script that calls this one.

and than call the script with the line:

/scripts/talend.sh $0.

Calling the script with $0 passes the name of the current script as an argument to the child which as shown above can be used to cd to the correct directory.

网友答案:

When you source /scripts/talend.sh the current directory is unchanged:

The scripts

# cat /scripts/talend.sh
echo "Talend: $(pwd)"
# cat /talend-job1_0.1/talend-job1_0.1/talend-job1/talend-job1.sh
echo Job1
. /scripts/talend.sh

Executing job1

# cd /talend-job1_0.1/talend-job1_0.1
# talend-job1/talend-job1.sh
Job1
Talend: /talend-job1_0.1/talend-job1_0.1

When you want to see the dir where the calling script is in, see get dir of script.

EDIT: When you want to have the path of the callling script (talend-job1.sh) without having to cd to that dir first, you should get the dir of the script (see link above) and source talend.sh:

# cat /scripts/talend.sh
cd "$( dirname "${BASH_SOURCE[0]}" )"
echo "Talend: $(pwd)"
网友答案:

In talend.sh get the name of the calling script and then the directory:

parent_cmd=$(ps -o args= $PPID)
set -- $parent_cmd
parent_cmd=$(dirname $2)

Update: as pointed by Charles Duffy in the comments below this will cause havoc when used with paths containing white-space or glob patterns.

If procfs is available you could read the content of /proc/$PPID/cmdline or if portability is a concern do a better parsing of the args.

网友答案:

In /scripts/talend.sh:

cd "$(dirname "$0")"

Or:

cd "$(dirname "$BASH_SOURCE")"

Another one is:

cd "$(dirname "$_")"
#This must be the first line of your script after the shebang line
#Otherwise don't use it

Note: The most reliable of the above is $BASH_SOURCE

分享给朋友:
您可能感兴趣的文章:
随机阅读: