tags:

views:

78

answers:

4

For example look at the following line of bash-code

eval `echo "ls *.jpg"`

It lists all jpgs in the current directory. Now I want it to just print the line to the prompt so I can edit it before executing. (Like key-up does for example)

How do I do that?


The reason for this question comes from a much more usefull alias:

alias ac="history 2 | sed -n '1 s/[ 0-9]*//p' >> ~/.commands; sort -fu ~/.commands > ~/.commandsTmp; mv ~/.commandsTmp ~/.commands"
alias sc='oldIFS=$IFS; IFS=$'\n'; text=(); while read line ; do text=( ${text[@]-} "${line}") ; done < ~/.commands; PS3="Choose command by number: " ; eval `select selection in ${text[@]}; do echo "$selection"; break; done`; IFS=$oldIFS'
alias rc='awk '"'"'{print NR,$0}'"'"' ~/.commands; read -p "Remove number: " number; sed "${number} d" ~/.commands > ~/.commandsTmp; mv ~/.commandsTmp ~/.commands'

Where ac adds or remembers the last typed command, sc shows the available commands and executes them and rc deletes or forgets a command. (You need to touch ~/.commands before it works)

It would be even more usefull if I could edit the output of sc before executing it.

A: 
history -s whatever you want

will append "whatever you want" to your bash history. Then a simple up arrow (or !! followed by enter if you have shopt histreedit enabled --- I think that's the option I'm thinking of, not 100% sure), will give you "whatever you want" on the command line, ready to be edited.

profjim
That's possible but it requires (hopefully unnecessary) user interaction. As the scripts purpose is minimizing the key-strokes I hope there is another solution.
tuner
Well, then why not have the script fake the command-line with `read -p "$PS1_this_is_nasty" -e -i "whatever you want"`
profjim
Maybe one step away from a first solution but what about tab-completion? I dont want to give away one convenience for the other.
tuner
I got readline in there with the `-e` flag. So tab-completion works, at least it works here for filepaths. What you won't get is programmatic completion, where it knows that the first argument should be an executable in PATH, the second a file, etc. Maybe there's some way to get that too, but it'll be harder. Anyway, you do still get simple filepath completion.
profjim
My bash dont know about -i and I cant get the example to run. However I am able to use completion but the given "argument" vanishes. How about a complete example based on the initial simple example with "ls *.jpg" which I want to change to "ls *.png"?
tuner
I'm using bash 4.1. Maybe `-i` is a recent innovation. I would just do `read -p '>' -e -i "ls *.jpg"`. If you don't have the `-i` option then I don't know what to suggest. I can tell you how to get the "ls *.jpg" written to the terminal in the right place, underneath the read prompt, but that wouldn't help because read wouldn't see it.
profjim
Hmm. Mine is 3.2.48. That could explain that. When nobody finds a better solution until tomorrow I will mark this answer as solution.
tuner
A: 

Some comments on your aliases:

Simplified quoting:

alias rc='awk "{print NR,\$0}" ~/.commands ...'

No need for tail and you can combine calls to sed:

alias ac="history 2 | sed -n '1 s/[ 0-9]*//p'..."

Simplified eval and no need for $IFS:

alias sc='text=(); while read line ; do text+=("${line}") ; done < ~/.commands; PS3="Choose command by number: " ; select selection in "${text[@]}"; do eval "$selection"; break; done'
Dennis Williamson
You're right with the simplification of ac. I changed the original post. rc must stay like it is because the quoting you intend won't work here - try it. sc also cannot be optimized by throwing away the $IFS cause it breaks the array in case there are spaces on the lines in ~/.commands.
tuner
@tuner07: The `+=` and the quoting of `"${text[@]}"` in the `select` statement eliminate the need for `IFS` and still handles spaces in the commands. I did try `rc` my way. The backslash escapes the dollar sign eliminating the need for the extra quotes. Try `sc` and `rc` with my changes. They work.
Dennis Williamson
A: 

@OP, you should really put those commands into subroutines, and when you want to use them, source it. (taken from dennis's answers)

rc(){
 awk "{print NR,\$0}" ~/.commands ...
}

ac(){
 history 2 | sed -n '1 s/[ 0-9]*//p'...
}

sc(){
 text=()
 while read line
 do 
     text+=("${line}") 
 done < ~/.commands
 PS3="Choose command by number: " 
 select selection in "${text[@]}" 
 do 
     eval "$selection"
     break
 done
}

then save it as "library.sh" or something and when you want to use it

$ source /path/to/library.sh  

Or

$ . /path/to/library.sh  
ghostdog74
Sure it reads better. But that was not my interest ;-) In fact it should be as short and easy as possible to allow me to easily set it up from my MidpSSH JavaME shell. Any suggestions for the question?
tuner
A: 

Maybe you could use preexec.bash?

http://www.twistedmatrix.com/users/glyph/preexec.bash.txt

(On a related note, you can edit the current command line by using ctrl-x-e as well!)

cheers,

tavod

tavod