I am trying to simplify my work with the help of Alias commands in my bash shell.
Problem Statement:
I want to copy different files from different directories to one single folder. The syntax i am using here is as below
cp <folder>/<file> <path>/file.dir
Here I want to save the destination file with filename.directory for easy identification. To achieve the same, I have written the below alias.
Alias Script
cp $Folder/$fileName ~/<path>/$fileName.$Folder
OR
cp $1/$2 ~/<path>/$2.$1
Expected output,
cp bin/file1 ~/Desktop/personal/file1.bin
cp etc/file2 ~/Desktop/personal/file2.etc*
However, It's failing at parsing the source file. i.e. $Folder
is not replaced with my first argument.
cp: cannot stat `/file1': No such file or directory
I am writing the above script only to reduce my command lengths. As I am not expert in the above code, seeking any expert help in resolving the issue.
Rather than using an alias you could use a function which you define in some suitable location such as .profile or .bashrc
For example:
mycp()
{
folder=$1
filename=$2
if [ $# -ne 2 ]
then
echo "Two parameters not entered"
return
fi
if [ -d $folder -a -r $folder/$filename ]
then
cp $folder/$filename ~/playpen/$filename.$folder
else
echo "Invalid parameter"
fi
}
There is no way a bash alias
can use arguments as you are trying to do. However, perl based rename
can probably help you here. Note that it will effectively mv
the files, not cp
them.
rename 's|([^/]*)/(.*)|/home/user/path/$2.$1|' */*
Limitations: You can only process the files in 1 sub-directory level.
So, below alias can work (with above limitation):
$ alias backupfiles="rename 's|([^/]*)/(.*)|/home/user/path/\$2.\$1|'"
$ backupfiles */*
You can make more sophisticated perl expression if you want to work with multi-directory-level file structure.
YAMC: Yet another myCp
This will work approx like cp
as last argument is destination dir:
myCp() {
local dest="${@:$#}" file
set -- "${@:1:$[$#-1]}"
for file in "$@"; do
cp -i "$file" "${dest%/}/${file##*/}.${file%%/*}"
done
}
could be used in that way:
myCp */* /path/to/destdir
To test this, you could replace cp -i
by echo "cp -i"
.
More sophisticated "myCp
"
myCp() {
local OPTIND=0_opt cpopt dest="" dbgcmd='' file name base
while getopts "ialdt:" opt; do
case $opt in
a | i | l ) cpopt+=$opt ;; # Forward [i|a|l] option to cp
d ) dbgcmd='echo' ;; # Debug option
t ) dest="$OPTARG" ;; # Target directory
* ) echo "Syntax error:" 1>&2; return ;;
esac
done
shift $[OPTIND-1]
[ -z "$dest" ] && dest="${@:$#}" && set -- "${@:1:$[$#-1]}"
for file in "$@"; do
name="${file##*/}" base="${file%/*}"
$dbgcmd cp ${cpopt+-}$cpopt "$file" "${dest%/}/$name.${base##*/}"
done
}
This will take last directory in source path as extension to copy files:
There is a -d
option to don't copy anything, but show result command:
myCp -dait /tmp/dedup /tmp/so/*/*
cp -ai /tmp/so/abc/lock /tmp/dedup/lock.abc
cp -ai /tmp/so/config/folder1 /tmp/dedup/folder1.config
cp -ai /tmp/so/config/folder2 /tmp/dedup/folder2.config
cp -ai /tmp/so/config/somefile1 /tmp/dedup/somefile1.config
or
myCp -dl /tmp/so/*/* /tmp/dedup/
cp -l /tmp/so/abc/lock /tmp/dedup/lock.abc
cp -l /tmp/so/config/folder1 /tmp/dedup/folder1.config
cp -l /tmp/so/config/folder2 /tmp/dedup/folder2.config
cp -l /tmp/so/config/somefile1 /tmp/dedup/somefile1.config
A directory contains some files say ~/Documents/file1.d contains newfile.txt
joe@indiana:~/Documents$ ls -l $file
total 1
-rw-r--r-- 1 joe staff 0 May 5 11:39 newfile.txt
Add the variable 'file' in .bashrc for example my .bashrc is shown here
alias ll='ls -la'
file=~/Documents/file1.d
Now whenever you copy to '$file' it will copy to file1.d directory under ~/Documents :)