How do I perform commands in another folder, without repeating the folder path?
Solution 1:
Simply use brace expansion:
mv /folder1/folder2/folder3/{file.txt,file-2013.txt}
This is equivalent to writing:
mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt
Brace expansion lets you supply more arguments, of course. You can even pass ranges to it, e.g. to create a couple of test folders, you can run mkdir test_{a..z}
, and starting with Bash 4, you can create zero-padded sequences as well, as in touch foo{0001..3}
, which creates foo0001
, foo0002
and foo0003
. The Bash Hackers Wiki has an article with a couple of examples for you.
If you have to use two different commands, use a subshell and cd
there first, as in @Ignacio's answer.
Solution 2:
Run the operation in a subshell.
( cd /folder1/folder2/folder3 && mv file.txt file-2013.txt )
The change of working directory won't be propagated to the parent shell.
Solution 3:
If you want clever, here's bash history expansion
mv /folder1/folder2/folder3/file.txt !#:1:h/file-2013.txt
I wouldn't use this myself since I find it impossible to memorize. I do occassionally use the vim equivalent, but have to look it up almost every time.
Solution 4:
You can set a variable. Of course this has the side-effect of leaving the variables around.
D=/folder1/folder2/folder3; mv $D/file.txt $D/file-2013.txt
Solution 5:
I like the other solutions, but here is another, implemented as a script with bash arrays, pushd, popd:
#!/bin/bash
set -e
# from http://stackoverflow.com/a/246128/178651
script_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# paths relative to the script
relative_paths=( \
path1 \
path2 \
path3 \
path4
)
for relative_path in "${relative_paths[@]}"
do
pushd "$script_path/$relative_path" > /dev/null 2>&1
pwd
mv filename1 filename2
# could do other stuff in this directory...
popd > /dev/null 2>&1
done
pushd "$script_path" > /dev/null 2>&1
# could do other stuff in same directory as script...
popd > /dev/null 2>&1