0

I have the following structure:

root_directory/  
          foo  
          bar/
             x/
               a.txt
               b.txt  
             y
             .a_file
           scripts/
                my_script.sh  

I want the my_script to copy the contents of bar/x to be under the root_directory
If I use:
cp -r ../bar/x .. it will break if I run the script outside the scripts directory.

How can I do this so that it works for both Mac and Linux?

  • 1
    Use absolute path? – Cyrus Oct 9 at 21:28
1

Or if you prefer relative paths, you could determine the absolute path to the script's directory with the help of the BASH_SOURCE array variable which holds the path to the script:

scripts=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
cp -R "$scripts"/../bar/x "$scripts"/..

GNU's cp doesn't care if -r or -R is used, but the BSD man page lists -r as discouraged, so better use the -R:

Historic versions of the cp utility had a -r option. This implementation supports that option; however, its use is strongly discouraged, as it does not correctly copy special files, symbolic links, or fifo's.

  • I mention without relative paths in the title – Jim Oct 10 at 7:48
  • @Jim Variable $scripts is absolute. Run your script from outside the scripts directory and test it… – Freddy Oct 10 at 10:34
  • How is $scripts/../bar/x better than ../bar/x? The .. is what I wanted to avoid – Jim Oct 10 at 21:00
  • 1
    The path "$scripts"/.. always points to your root directory (parent directory of scripts) while .. points to the parent directory from where your script was started (parent of $PWD). If you don't want to use .., then use Nasir Riley's solution and accept his answer. – Freddy Oct 10 at 21:25
0

Your command is telling it to copy the contents of the directory bar/x that is located above the working directory as denoted by ../bar/x. If you aren't in the scripts directory then it's not going to work because bar/x won't be located above it. In the case that you are working elsewhere in the system and there happens to be another bar/x located in the directory above where your are working then it will copy it but it won't be the same bar/x that is located above the root_directory/scripts directory. The only way to get it to work anywhere on the system is to use the absolute path:

cp -r /path/to/root_directory/bar/x /path/to/root_directory
0

If for some reason you don't want/need full paths, this is my proposal:

dir=$(cd $(dirname "$0"); pwd -P)
cd $dir
cd ..
root=$PWD
cd bar
bar=$PWD
cp -r $bar/x $root

Get current script's full path

dir=$(cd $(dirname "$0"); pwd -P)

Go to dir, then back a step, you are in the "root" dir, assign to a variable:

cd $dir
cd ..
root=$PWD

Got to bar, assign it to a variable, then use the cp command using the variables

cd bar
bar=$PWD
cp -r $bar/x $root
  • I mention without relative paths in the title – Jim Oct 10 at 7:48
  • Sorry. Anyway, my answer doesn't really use relative paths. What it does, is get the full paths starting withs the script's path. So all you need is the later and nothing else. It can be helpful if you move your directory structure to another place. – guillermo chamorro Oct 10 at 13:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.