LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Shell script help: How to pass a directory path to the script? (https://www.linuxquestions.org/questions/programming-9/shell-script-help-how-to-pass-a-directory-path-to-the-script-668752/)

dv502 09-09-2008 03:31 PM

Shell script help: How to pass a directory path to the script?
 
Hey everyone,

First, I want to say I can run my scripts anywhere within my home directory as I added my home bin directory to my environment path.
So that you don't misunderstand, this is not a path issue.

Example 1

cd path/to/somewhere/files/
myscript

I have some shell scripts that process media files. In order for me to process the files with my script, I have to change directory to where my media files are and then execute my script.

Example 2

myscript path/to/somewhere/files/

In this example, the directory path is pass to the script. How can I do this?

Before you say, I can add a path string in a variable in my script, like so:

dirpath="path/to/somewhere/files"
cd $dirpath

I use this method in some of my scripts, but is a way I can give the path to the script -- rather than have the path fixed in a string variable.

I appreciate your comments and thanks for your help in advance :)

david1941 09-09-2008 03:39 PM

Executables are executed with a search of your $PATH variable but parameters passed to the script are expanded by the shell and do NOT use your path. Normally, for variable data file, one would include the path with the target file or one will get the file relative to the working directory. You can get the working directory with the command, pwd (print working directory)

Dave

ta0kira 09-09-2008 03:51 PM

If you know what argument number it will be, just do this:
Code:

cd "$1" #argument #1 is the path
Remember that the script is executed from the directory the call is made from, e.g. if the script is saved in ~ and you're in / and call ~/myscript.sh then all commands in the script will be executed in / by default. Normally I'll just record the current path, then change to the directory the script is in as a start (in case I keep config files or something with the script):
Code:

#!/bin/bash

current="$(pwd)"
cd "$(dirname "$(readlink -f "$0")")"

echo "'$current'" '->' "'$(pwd)'" #show paths for demo purposes

cd "$1" #change to the directory provided (relative to the script)

echo "'$1'" '->' "'$(pwd)'" #show new path for demo purposes

This will make your path relative to the script, but if you want it relative to the path it was executed from, remove the first cd.
ta0kira

dv502 09-09-2008 04:02 PM

Thanks david1941 for your reply.

So, this means that a shell script can't take a directory path as part of the argument as a compiled binary executable would. (i.e ELF 32-bit LSB executable)

I guess I would have to add the path in a string variable as mentioned above in my post.

Maybe one day the shell developers would add that functionality to the bash shell.

BTW, can the other shells like csh,ksh and zsh take a directory path as an argument?

dv502 09-09-2008 04:14 PM

Quote:

Originally Posted by ta0kira (Post 3274981)
If you know what argument number it will be, just do this:
Code:

cd "$1" #argument #1 is the path
Remember that the script is executed from the directory the call is made from, e.g. if the script is saved in ~ and you're in / and call ~/myscript.sh then all commands in the script will be executed in / by default. Normally I'll just record the current path, then change to the directory the script is in as a start (in case I keep config files or something with the script):
Code:

#!/bin/bash

current="$(pwd)"
cd "$(dirname "$(readlink -f "$0")")"

echo "'$current'" '->' "'$(pwd)'" #show paths for demo purposes

cd "$1" #change to the directory provided (relative to the script)

echo "'$1'" '->' "'$(pwd)'" #show new path for demo purposes

This will make your path relative to the script, but if you want it relative to the path it was executed from, remove the first cd.
ta0kira

Thanks for the code ta0kira,

I admit it looks confusing.

david1941 09-09-2008 04:31 PM

You could set up a special path (for example, a $MUSICPATH) in your environment and search for files using that variable in your executable. The man xxxxxx command does that in the man executable using the environment variable $MANPATH. If it is going to be an argument to your executable, it may be easier to just pass the full path name of the target file (directory) to the command though. Of course you could also pass the path as a separate parameter. What are you trying to do?? Your post said "process some media files". It would seem that indicates you want to "Process" in some specific directory. If so, you could code the target directory in the script or pass it to the script as a parameter as in the first example shown in the post by ta0kira (above).

Dave

dv502 09-09-2008 05:18 PM

I was using the first post as a scenario. Like I said, I can run my scripts anywhere. What I want to do is pass the directory path as an argument relative to where I ran the script. For example, lets say I opened my terminal and my current directory is /home/smith and my media files are in multimedia/audio/wavs.

Instead of changing to the multimedia/audio/wavs folder and then running the script, I could instead stay where I am (i.e /home/smith) and just pass the directory where the files are located to the script. Example

myscript multimedia/audio/wavs or

myscript multimedia/audio/wavs/somefile.wav

I could include the path in a variable or global variable, I know how to do that. But, I want the option to be able to pass different paths to the script, rather than have it fixed in a variable.

i.e myscript multimedia/audio/wavs
i.e myscript multimedia/audio/wavs1
etc...

ta0kira gave me some clues to start with and I will see how it goes.

jan61 09-09-2008 05:43 PM

Moin,

ta0kira showed the solution in his first code example exactly as you wanted. $1 is the first command line argument - you can use it to cd into this directory (when your script exits, you will find yourself in the directory where you started the script; the cd takes no effect in your current shell) or you can use it to ls this directory and process the listed files.

Jan

Mr. C. 09-09-2008 06:55 PM

See Week 4 Notes "Arguments" @ http://cis68b1.mikecappella.com/

chrism01 09-09-2008 08:07 PM

Y, ta0kira's 1st line is the answer you want. The rest of his post was just pointing out potential pitfalls if you're not careful to differentiate between where you ran the script from and where it may need to be to do its job correctly.

dv502 09-09-2008 08:35 PM

I got the script to do what I wanted, well almost
 
Code:

#!/bin/bash
workdir=$(dirname "$1")

help () {

        echo "usage: $(basename $0) name of flv's files"
}

if [ $# -lt 1 ] ;
then
        help
        exit 1
fi

for i in $@
do
        ffmpeg -i  "$i" -y $workdir/$(basename "$i" .flv).avi
done

The clue that ta0kira gave me was the command dirname.

I tested the script both ways. First I change to the directory where the flv files were i.e multimedia/videos. Then I ran my script flv2avi and the script converted the flv files to avi versions. Good.

Next, I deleted the avi files for the next test. I cd to my home directory and ran my script as so.

Code:

[david@mylinuxbox ~]$ flv2avi multimedia/videos/*.flv
When the script finished, I was still at my home directory where I started the script from. I ran ls multimedia/videos/ and behold
the script converted the flv files to avi files. So it worked.

The only glitch is that I can't run the script this way

flv2avi multimedia/videos/

Because the dirname will strip off the videos part and leave only the multimedia part. So for it to work, I need to pass at least one file or a combinations of files via wildcards etc. See the man page for dirname, it will explain it more better.

flv2avi multimedia/videos/sample.flv
flv2avi multimedia/videos/*.flv
flv2avi multimedia/videos/name*.flv

All these are vaild and worked.

Mr. C. 09-09-2008 08:42 PM

Add a test to check the script's argument as being either a file or directory: Don't strip if its a directory:

Code:

if [ -d "$1" ] ; then
  echo its a directory
elsif [ -f "$1" ], then
  echo its a file
else
  echo some other type
fi


dv502 09-09-2008 10:14 PM

Thanks to all of you who replied to my post for your comments and suggestions. I have a better flv2avi script which I didn't want to mess with, so I wrote that quick script to practice the dirname command suggested by ta0kira.

I will continue to tweak the script to fix the glitch. Anyway, I got it to do what I wanted, which is to pass a directory path of files to the script. It's not perfect, but it's gets the job done.

:)

- Cheers

Again, thanks to you all....

dv502 09-10-2008 03:07 AM

Update
 
Code:

#!/bin/bash

help () {

        echo "usage: $(basename $0) path to flv's files"
}

convert2avi () {
        for i        # short for "for i in $*"
        do
        ffmpeg -i "$i" ${i%.flv}.avi
        done
}


if [ $# -lt 1 ] ;
then
        help
        exit 1
fi


if [ -d "$1" ] ;
then cd "$1"
convert2avi *.flv
else [ -f "$1" ] ;
convert2avi $@       
fi

Here I am using the if/else statements as suggested by Mr. C.
I tried using dirname with the if/else statements on the same script, but the output of dirname confuse the if/else statements. I'm finding a good use for the dirname command in another script that is working great.



Anyway, I gave the flv2avi script three tests. The first test I change to the directory where the flv files were and ran the script. It PASSED. Next, I deleted the avi files for the second test.

Code:

cd multimedia/videos
flv2avi *

The second test, I change to my home directory and pass the directory path as an arguement to the script. It PASSED. And I deleted the avi files for the third test.

Code:

cd
flv2avi multimedia/videos

The third test, I supplied the file(s) for it to process. Still at my home directory, I ran

Code:

flv2avi multimedia/videos/Linux_HOWTO_Video_Editing_with_ffmpeg.flv
And, it PASSED.

Thanks again to everyone for the comments and special thanks to ta0kira and Mr. C. for the code suggestions.

- Cheers


All times are GMT -5. The time now is 04:27 AM.