Prompt for file path: home directory alias and case-sensitive tab completion - bash

I am writing a shell script that prompts the user for a file path:
read -e -p "Enter the path to the file: " FILEPATH
I am then using this file path to perform operations – namely to compress a folder.
(cd "$FILEPATH"; tar -cvz *) > /tmp/torrent.tar.gz;
At the prompt, if I use the ~ alias (home directory), then the shell script doesn't seem to understand this, as the tar function compresses the wrong path. Is there anyway I can allow for this alias?
Also, tab completion seems to be case-sensitive at the prompt. I was wondering how I can change that?

Example using eval:
read -e -p "Enter the path to the file: " FILEPATH
eval FILEPATH=$FILEPATH
cd $FILEPATH
echo $PWD
In your case it becomes:
read -e -p "Enter the path to the file: " FILEPATH
eval FILEPATH=$FILEPATH
(cd "$FILEPATH"; tar -cvz *) > /tmp/torrent.tar.gz;
To deal with spaces you can use sed:
read -e -p "Enter the path to the file: " FILEPATH
FILEPATH=$(echo $FILEPATH | sed 's/ /\\ /')
eval FILEPATH=$FILEPATH
cd "$FILEPATH"
echo $PWD

You could apply the substitution yourself like this:
filepath=${filepath/\~/$HOME}
I don't know whether there's a way to get the shell to do it for you.
Here's an answer to your other question: https://superuser.com/questions/90196/case-insensitive-tab-completion-in-bash

Related

Bash script to change directory from user input

Whenever I execute this script it says: no such file or directory.
I'm not sure what I'm doing wrong here. I put quotes around it just in case if there is a space in the directory's name.
#!/bin/bash
read -p "Enter destination: " folder
folder=$(sed -e 's/^/"/' -e 's/$/"/' <<< $folder)
cd $folder
It is better to use quotes in the cd command, regardless of whether the directory has spaces or not, like this:
#!/bin/bash
read -p "Enter destination: " folder
cd "$folder"
pwd
Test:
Another solution (use with caution as it may cause other problems) is using eval in your code:
#!/bin/bash
read -p "Enter destination: " folder
folder=$(sed -e 's/^/"/' -e 's/$/"/' <<< $folder)
eval cd $folder
References:
Bash script to cd to directory with spaces in pathname

Store output of command in sftp to variable and list

My aim is to create a shell script such that it logins and filter the list of files available and select a file to get. Here I need to run commands like in bash.
My sample code is:
sshpass -p password sftp user#10.10.10.10 <<EOF
cd /home/
var=$(ls -rt)
echo $var
echo "select a folder"
read folder
cd $folder
filen=&(ls -rt)
echo $filen
echo "select a file"
read name
get $name
bye
EOF
The above approach will not work. Remember that the 'here document' (<<EOF ... EOF) is evaluate as input to the sftp session. Prompts will be displayed, and user input will be requested BEFORE any output (ls in this case) will be available from sftp.
Consider using lftp, which has more flexible construct. In particular, it will let you use variables, create command dynamically, etc.
lftp sftp://user#host <<EOF
cd /home
ls
echo "Select Folder"
shell 'read folder ; echo "cd $folder" >> temp-cmd'
source temp-cmd
ls
echo "Select Folder"
shell 'read file ; echo "get $file" >> temp-cmd'
source temp-cmd
EOF
In theory, you can create similar constructs with pipes and sftp (may be a co-process ?), but this is much harder.
Of course, the other alternative is to create different sftp sessions for listing, but this will be expensive/inefficient.
After some research and experimentation, found a way to create batch/interactive sessions with sftp. Posting as separate answer, as I still believe the easier way to go is with lftp (see other answer). Might be used on system without lftp
The initial exec create FD#3 - pointing to the original stdout - probably user terminal. Anything send to stdout will be executed by the sftp in the pipeline.
The pipe is required to allow both process to run concurrently. Using here doc will result in sequential execution. The sleep statement are required to allow SFTP to complete data retrieval from remote host.
exec 3>&1
(
echo "cd /home/"
echo "ls"
sleep 3 # Allow time for sftp
echo "select a folder" >&3
read folder
echo "cd $folder"
echo "ls"
sleep 3 # Allow time for sftp
echo "select a file" >&3
read name
echo "get $name"
echo "bye"
) | sshpass -p password sftp user#10.10.10.10
I would suggest you to create a file with pattern of the files you want downloaded and then you can get files downloaded in one single line:
sftp_connection_string <<< $"ls -lrt"|grep -v '^sftp'|grep -f pattern_file|awk '{print $9}'|sed -e 's/^/get -P /g'|sftp_connection_string
if there are multiple definite folders to be looked into, then:
**Script version**
for fldr in folder1 folder2 folder3;do
sftp_connection_string <<< $"ls -lrt ${fldr}/"|grep -v '^sftp'|grep -f pattern_file|awk '{print $9}'|sed -e "s/^/get -P ${fldr}/g"|sftp_connection_string
done
One-liner
for fldr in folder1 folder2 folder3;do sftp_connection_string <<< $"ls -lrt ${fldr}/"|grep -v '^sftp'|grep -f pattern_file|awk '{print $9}'|sed -e "s/^/get -P ${fldr}\//g"|sftp_connection_string;done
let me know if it works.

How to autocomplete path and file in a bash script?

I am trying to write a bash script, where I want to read a path and a file with autocompletion. I used [read -e -p "path name:" pathname]. This works fine, but when I try [read -e -p $pathname filename], the file autocompletion just doesn't work. Can someone help me? Thanks in advance :)
The file autocompletion works from the current directory. If you want it to work in a given directory, you have to change the current directory to it:
read -e -p "path name:" pathname
cd $pathname
read -e -p $pathname filename

change terminal title according to the last 2 directories in the path

I want to change the title everytime I enter a new directory ( when using cd ), but show only the last 2 directories. I'm using tcsh at work and bash at home.
For example: if I'm at folder ~/work/stuff and I write: cd 1.1, I want my new title to be stuff/1.1.
I already know how to change the title everytime I change the folder:
alias cd 'cd \!*; echo "\033]0;`pwd`\a"'
And I know how to take only the 2 last directories:
pwd | awk -F / -v q="/" '{print $(NF-1)q$NF}'
The question is how to combine these two, or how to do it in a different way?
It doesn't have to be through alias to cd.
What I did was creating a script file named titleRename.tcsh with the following code:
#!/bin/tcsh -f
set fullpath = "`pwd`\a"
set newTitle = `echo $fullpath | awk -F / '{OFS="/"; if(NF > 2){printf $(NF-2);printf "/"; printf $(NF-1); printf "/"; print $NF;}else print $0}'`
echo "\033]0;$newTitle"
It splits the pwd with awk, getting only the last 3 directories, and then it prints to the tab name.
Then I added in the .alias file the following:
alias cd 'cd \!*; <dir of script file>/titleRename.tcsh'
Now the title name changes automatically whenever I cd to a different directory :)
I originally thought you should be able to use the full command where you have pwd in backticks in the alias ie:
alias cd 'cd \!*; echo "\033]0;`pwd | awk -F / -v q="/" '{print $(NF-1)q$NF}'`\a"'
but now I realise there may be problems with the nested quoting. And that wouldn't work in bash anyway; I don't think there's a way to access command parameters in an alias.
Instead of aliasing cd you should update the title with the prompt. I don't know tcsh, but in bash the normal way to do this sort of thing is with the special pseudo-variable PS1:
# Minimalist prompt
PS1="\$ "
# Additionally set terminal title to cwd
case "$TERM" in
xterm*|rxvt*)
PROMPT_DIRTRIM=2
PS1="\033]0;\w\a$PS1"
;;
*)
;;
esac
That won't trim the directory name quite the way you were doing it, but unfortunately I can't get the quoting right to be able to use the escape sequence in PROMPT_COMMAND.

OSX Bash Script working with Files/Folders with spaces in the name

I'm trying to build a BASH script on OS X (10.6/10.7) to process a folder called QCExports which has folders with people's names in it in the format "LAST, First", i.e. "BOND, James".
When I run the following script, everything works but it falls over on folder or filenames with a space in them.
Script Code:
#!/bin/bash
echo "QuickCeph Export Script"
#Set Path to Process & Paths to Copy To
pathToQCExports=/Users/myuser/Desktop/QCExports
sureSmilePath=/Users/myuser/Desktop/QCExportsForSureSmile
sesamePath=/Users/myuser/Desktop/QCExportsForSesame
blankReplace=""
#Process Each Name
find $pathToQCExports -type d | while read name ; do
#escaping the folder with a space in the name
nameParsed=${name/", "/",\ "}
echo "Processing: "$nameParsed
pathSureSmile=${nameParsed/$pathToQCExports/$sureSmilePath}
pathSesame=${nameParsed/$pathToQCExports/$sesamePath}
mkdir $pathSesame
mkdir $pathSureSmile
echo "Folders Created"
#Copy For SureSmile
echo ${pathSureSmile}"/Suresmile-Frontal\ Photo.jpg" ${pathSureSmile}"/Suresmile-Frontal\ Photo.jpg"
#cp `${$pathSureSmile}"/Suresmile-Frontal\ Photo.jpg" ${pathSureSmile}"/Suresmile-Frontal\ Photo.jpg"`
#Copy For Sesame
echo ${pathSesame}"/Suresmile-Frontal\ Photo.jpg" ${pathSesame}"/S02.jpg"
#cp `${pathSesame}"/Suresmile-Frontal\ Photo.jpg" ${pathSesame}"/S02.jpg"`
done
echo "Completed";
Output:
QuickCeph Export Script
Processing: /Users/myuser/Desktop/QCExports/BOND,\ James
mkdir /Users/myuser/Desktop/QCExportsForSesame/BOND,\ James
mkdir: James: File exists
mkdir /Users/myuser/Desktop/QCExportsForSureSmile/BOND,\ James
mkdir: James: File exists
Folders Created
/Users/myuser/Desktop/QCExportsForSureSmile/BOND,\ James/Suresmile-Frontal\ Photo.jpg /Users/myuser/Desktop/QCExportsForSureSmile/BOND,\ James/Suresmile-Frontal\ Photo.jpg
/Users/myuser/Desktop/QCExportsForSesame/BOND,\ James/Suresmile-Frontal\ Photo.jpg /Users/myuser/Desktop/QCExportsForSesame/BOND,\ James/S02.jpg
Completed
On OS X usually in the terminal, you use a \ to escape a space in a folder or filename, but that doesn't seem to work.
I notice that it's interpreting the spaces as a normal space would be interpreted on the command line and thinking I want to execute the command on two files - i.e. it's not passing the \ onwards. I end up with a folder called "Bond,\" and a folder called "James" in the folder I execute the script from.
Note, I deliberately have the cp commands # out at the moment, so they aren't being executed... the problem is the same for both creating the folders & copying the filenames.
If I copy and paste the "echo'd" version of these commands into a terminal window, the commands work! But when BASH executes them, it doesn't respect the . :(
Any ideas?
Thanks!!
John
See my modifications on your script, you don't have to substitute spaces like you tried.
Moreover, you must choose if you backslash the spaces or if you are using quotes.
The simple way is to use double quotes.
Good doc about quotes, see http://mywiki.wooledge.org/Quotes and http://wiki.bash-hackers.org/syntax/words
#!/bin/bash
echo "QuickCeph Export Script"
#Set Path to Process & Paths to Copy To
pathToQCExports=/Users/myuser/Desktop/QCExports
sureSmilePath=/Users/myuser/Desktop/QCExportsForSureSmile
sesamePath=/Users/myuser/Desktop/QCExportsForSesame
blankReplace=""
#Process Each Name
find $pathToQCExports -type d | while read nameParsed ; do
echo "Processing: $nameParsed"
pathSureSmile="${nameParsed/$pathToQCExports/$sureSmilePath}"
pathSesame="${nameParsed/$pathToQCExports/$sesamePath}"
mkdir "$pathSesame"
mkdir "$pathSureSmile"
echo "Folders Created"
#Copy For SureSmile
echo "${pathSureSmile}/Suresmile-Frontal Photo.jpg" "${pathSureSmile}/Suresmile-Frontal Photo.jpg"
#Copy For Sesame
echo "${pathSesame}/Suresmile-Frontal Photo.jpg" "${pathSesame}/S02.jpg"
done
echo "Completed"

Resources