echoing the last command inside bash function

6 views
Skip to first unread message

Flash

unread,
Jun 29, 2022, 4:24:40 AMJun 29
to
$ cat /tmp/last-command.sh
last_command() {
echo !!
}

$ . /tmp/last-command.sh

$ echo !!
echo . /tmp/last-command.sh
. /tmp/last-command.sh

OK, !! is rightly evaluated.

$ last_command
!!

Now instead !! is not rightly evaluated.
Why?

Joe Beanfish

unread,
Jun 29, 2022, 10:31:11 AMJun 29
to
!! accesses the history. I think history is only relevant to interactive
command line entries, not scripts, so apparently not available in function
either? Doesn't appear to work in an alias either.

Java Jive

unread,
Jun 29, 2022, 10:59:50 AMJun 29
to
On 29/06/2022 09:24, Flash wrote:
> $ cat /tmp/last-command.sh
> last_command() {
>     echo !!
> }
>
> $ . /tmp/last-command.sh
>
> $ echo !!
> echo . /tmp/last-command.sh
> .. /tmp/last-command.sh
>
> OK, !! is rightly evaluated.
>
> $ last_command
> !!
>
> Now instead !! is not rightly evaluated.
> Why?

I've never used !! - following is a standard script header I use to
have a script log itself. Of course this is just my choice from the
possibilities, others may advise differently ...

#!/bin/sh
# Log output
# Extract script name from $0
ME="$(echo $0 | /bin/sed s:^/.*/:: | /bin/sed s:\\.sh$::)"
# Use script name to create dated log name
LOG="/var/log/${ME}-$(date +%Y%m%d-%H%M%S).log"
exec > ${LOG} 2>&1
echo "Running $0 $* ..."
echo

# Rest of script

--

Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk

J.O. Aho

unread,
Jun 30, 2022, 6:04:22 AMJun 30
to
For in script you have the history expand by default disabled.

If you want it to be like in command line, then you need to enable the
history expand

--- bash script ---
#!/bin/bash
set -o history -o histexpand

ls /tmp > /dev/null
echo "CMD='"!:0"'"
--- eof ---

but it has it's bad sides as you see, you may use trap for better
debugging, but will not really works as you seems to want and I can't
see an user case where you would want to do your example.

--

//Aho

Kenny McCormack

unread,
Jun 30, 2022, 8:04:48 AMJun 30
to
In article <ji5ap2...@mid.individual.net>,
J.O. Aho <us...@example.net> wrote:
...
>> Now instead !! is not rightly evaluated.
>> Why?
>
>For in script you have the history expand by default disabled.
>
>If you want it to be like in command line, then you need to enable the
>history expand
>
>--- bash script ---
>#!/bin/bash
>set -o history -o histexpand
>
>ls /tmp > /dev/null
>echo "CMD='"!:0"'"
>--- eof ---
>
>but it has it's bad sides as you see, you may use trap for better
>debugging, but will not really works as you seems to want and I can't
>see an user case where you would want to do your example.

Two comments:
1) OP has not stated what his actual goal is, so we don't know anything
about what the actual use case is. We may not ever hear back from
OP, so we are left guessing. At least one poster on the thread has
speculated that the goal is to capture the script name so that it
can be used to log file entries and so on. If that is the goal,
then there are many easier, better ways to do that.

2) OP might be looking for $_, which generally holds the name of the
last command executed (at least in bash; don't know about any other
shells). This works in scripts. I sometimes use $_ to tell me
whether or not a loop found a match (i.e., succeeded) or just ended
because the loop ended. For example:

for i in {list of files};do
[ $i matches or whatever ] && break
done
[ $_ = break ] && echo "A match was found!" || echo "Loop exited without finding a match"

--
Watching ConservaLoons playing with statistics and facts is like watching a
newborn play with a computer. Endlessly amusing, but totally unproductive.

Flash

unread,
Jun 30, 2022, 10:50:28 AMJun 30
to
Il 30/06/22 14:04, Kenny McCormack ha scritto:
> OP has not stated what his actual goal is, so we don't know anything
> about what the actual use case is.

$ tree dir | cat >> commands-output

After a few days (in which I will have forgotten what I did exactly, in
which I forgot the command I have in given...)

$ cat commands-output
dir
├── a
├── b
└── c

The output refers to what?
Or rather, Output refers to which command?

So at the first line I would have liked to have the reference command,
and then everything else.

Example

$ cat commands-output
REFERENCE COMMAND: $ tree dir
dir
├── a
├── b
└── c

It can be done?

-----BEGIN PGP MESSAGE-----

hQGMAyHa6HqE1N3qAQwAivFYgm6kp+JCAOLdqF8HrJIEGO/bGqPpxzKGSlBURMAd
tMmrZ5R66x6UhHCfV26+8+4R53A9a0cqCFZdM1imSorGA0A0vRLbz3AQATvR7Cf4
t5/MLKC4v8vHPKU8NA2ny+qaEBuLSPfiidPemqjRN8nLWUqUDh1sxevY8avYNp2L
C8B1uTrDTGSG7Al7D7QacZP00WvfTI8JtgVeG+6aFwEJy+3SLMp/WqFdK18Vp/IL
tgWDyIL1PMvcvA+GFlWCt9P/ULYBOfnqhfvGbkSFCBXwzRRvPxqy0BTARZm2hNRU
4fKHRj++msAW6BihU3kkTq95H/mfAn1RIwIqwX6bF7s/DprdqUtJ5Bx6H79dM6A4
hQyieK3oGdLuWtWxoxLu8akYuwJOJPy9vhqsPGIcTdT3109yg1CUfz+URZaF7HPo
dXKk8fbHVlyhOZ2MrURWxCAjo1ngg3F58Xx1jf3rpXa3xCKHmDLnJUGcYoVd59wh
LeeRHNrGoNr8ST0ipGsF0pYB/QLCDT/aXxIBC31We5eqNhGUgseh8ZqYKfWiU0sj
E90+En2dADXGj5N/UkDr6xMoylDsO94a7FMxQZ07H5UVihYvGBaqtrnU4uMLOGs9
nle7QFLT5toWutoh44bZgeXkMsw1BAzijpg/FByro5pudb9qEum//KTDmGt+HaXd
hjokxZtlFYPOOXmEUQO3XvMnayu+Vt4=
=jI13
-----END PGP MESSAGE-----

Lew Pitcher

unread,
Jun 30, 2022, 11:15:45 AMJun 30
to
On Thu, 30 Jun 2022 16:50:25 +0200, Flash wrote:

> Il 30/06/22 14:04, Kenny McCormack ha scritto:
>> OP has not stated what his actual goal is, so we don't know anything
>> about what the actual use case is.
>
> $ tree dir | cat >> commands-output

UUOC. Try
tree dir >>commands-output
instead

>
> After a few days (in which I will have forgotten what I did exactly, in
> which I forgot the command I have in given...)
>
> $ cat commands-output
> dir
> ├── a
> ├── b
> └── c
>
> The output refers to what?
> Or rather, Output refers to which command?
>
> So at the first line I would have liked to have the reference command,
> and then everything else.
[snip]
> It can be done?

Yes

Try
echo "tree dir" | script -a commands-output

See script(1) ("man 1 script") for details


> -----BEGIN PGP MESSAGE-----
[snip]
> -----END PGP MESSAGE-----
And, why the encrypted message?

HTH
--
Lew Pitcher
"In Skills, We Trust"

Kenny McCormack

unread,
Jun 30, 2022, 11:40:42 AMJun 30
to
In article <t9kemj$1u4fr$1...@dont-email.me>,
Lew Pitcher <lew.p...@digitalfreehold.ca> wrote:
...
>Try
> echo "tree dir" | script -a commands-output

At least in principle: script -a commands-output <<< "tree dir"
But I actually don't know if script reads from stdin like this anyway.

So:

script -ac "tree dir" commands-output

Note: I do endorse using script for this. A useful command that many don't
know about.

--
To most Christians, the Bible is like a software license. Nobody
actually reads it. They just scroll to the bottom and click "I agree."

- author unknown -

Lew Pitcher

unread,
Jun 30, 2022, 11:59:48 AMJun 30
to
On Thu, 30 Jun 2022 15:40:40 +0000, Kenny McCormack wrote:

> In article <t9kemj$1u4fr$1...@dont-email.me>,
> Lew Pitcher <lew.p...@digitalfreehold.ca> wrote:
> ...
>>Try
>> echo "tree dir" | script -a commands-output
>
> At least in principle: script -a commands-output <<< "tree dir"
> But I actually don't know if script reads from stdin like this anyway.
>
> So:
>
> script -ac "tree dir" commands-output

Nope. The OP "... would have liked to have the reference command,
and then everything else." script -c does /not/ write the command
into the typescript file.

11:53 $ cat tree_ac.txt
cat: tree_ac.txt: No such file or directory

11:54 $ script -ac "tree tmp" tree_ac.txt
Script started, file is tree_ac.txt
tmp
|-- a.out
|-- tst
`-- tst.c

0 directories, 3 files
Script done, file is tree_ac.txt

11:54 $ cat tree_ac.txt
Script started on Thu 30 Jun 2022 11:54:09 AM EDT
tmp
|-- a.out
|-- tst
`-- tst.c

0 directories, 3 files

Script done on Thu 30 Jun 2022 11:54:09 AM EDT
11:54 $

But
echo "command" | script
/does/ write the command into the typescript file

11:56 $ cat tree_a.txt
cat: tree_a.txt: No such file or directory

11:56 $ echo "tree tmp" | script -a tree_a.txt
Script started, file is tree_a.txt
tree tmp
11:56 $ tree tmp
tmp
|-- a.out
|-- tst
`-- tst.c

0 directories, 3 files
11:56 $ exit
Script done, file is tree_a.txt

11:56 $ cat tree_a.txt
Script started on Thu 30 Jun 2022 11:56:30 AM EDT
tree tmp
11:56 $ tree tmp
tmp
|-- a.out
|-- tst
`-- tst.c

0 directories, 3 files

11:56 $

Script done on Thu 30 Jun 2022 11:56:30 AM EDT
11:56 $

> Note: I do endorse using script for this. A useful command that many don't
> know about.




--

Flash

unread,
Jun 30, 2022, 12:15:05 PMJun 30
to
Il 30/06/22 17:15, Lew Pitcher ha scritto:
> [...]
$ rm typescript
$ echo "tree" | script | cat -n
1 Script iniziato, il file è typescript
2 tree
3 $ tree
4 .
5 ├── file1
6 ├── file2
7 └── typescript
8
9 0 directories, 3 files
10 $ exit
11 Script effettuato, il file è typescript
$ test -f typescript && echo FILE FOUND
FILE FOUND

I want to send the output only to the "cat -n" command and not to the
typescript file.

J.O. Aho

unread,
Jun 30, 2022, 1:41:57 PMJun 30
to

On 30/06/2022 16.50, Flash wrote:
> Il 30/06/22 14:04, Kenny McCormack ha scritto:
>>  OP has not stated what his actual goal is, so we don't know anything
>>     about what the actual use case is.
>
> $ tree dir | cat >> commands-output
>
> After a few days (in which I will have forgotten what I did exactly, in
> which I forgot the command I have in given...)


so you want something like:

--- runcmd ---
#!/bin/bash
CMD=$1
echo "$CMD"
eval $CMD
--- eof ---

runcmd "tree /dir" >> commands-output

Maybe better to bookmark the webpage where you found the command line in
the first place ;)

history is a good command to get to know what you done before and you
can add time stamp to it too

https://www.cyberciti.biz/faq/unix-linux-bash-history-display-date-time/

other alternatives:
- use more describing file names so you know what the content is and
how to regenerate it
- Use bash audit and look in the logs.
- make a script that does your work and can add a comment what input
parameters was used


--
//Aho

Richard Kettlewell

unread,
Jun 30, 2022, 3:28:20 PMJun 30
to
History expansion happens before almost all other parsing (see the man
page for specifics). Using it in a shell function won’t do anything very
useful for that reason. For instance, interactively:

richard@sfere:~/junk$ wibble
-bash: wibble: command not found
richard@sfere:~/junk$ f() {
> echo !!
echo wibble
> }
richard@sfere:~/junk$ type f
f is a function
f ()
{
echo wibble
}

History is also disabled when reading a file rather than a terminal,
which is why the function defined in the file stll contains !!.

richard@sfere:~/junk$ cat t
g() {
echo !!
}
richard@sfere:~/junk$ . t
richard@sfere:~/junk$ type g
g is a function
g ()
{
echo !!
}

--
https://www.greenend.org.uk/rjk/

Lew Pitcher

unread,
Jun 30, 2022, 3:44:58 PMJun 30
to
On Thu, 30 Jun 2022 18:15:02 +0200, Flash wrote:

[snip]
> I want to send the output only to the "cat -n" command and not to the
> typescript file.

Ahhh. But that's /not/ what you said in the post I replied to

On Thu, 30 Jun 2022 16:50:25 +0200, Flash wrote:
Flash> $ tree dir | cat >> commands-output
Flash>
Flash> After a few days (in which I will have forgotten what I did exactly, in
Flash> which I forgot the command I have in given...)
...
Flash>
Flash> So at the first line I would have liked to have the reference command,
Flash> and then everything else.

You didn't say that you wanted the data line-numbered

Anyway, I answered the question you asked.

Joe Beanfish

unread,
Jul 1, 2022, 9:33:08 AMJul 1
to
On Thu, 30 Jun 2022 16:50:25 +0200, Flash wrote:

> Il 30/06/22 14:04, Kenny McCormack ha scritto:
>> OP has not stated what his actual goal is, so we don't know anything
>> about what the actual use case is.
>
> $ tree dir | cat >> commands-output
>
> After a few days (in which I will have forgotten what I did exactly, in
> which I forgot the command I have in given...)
>
> $ cat commands-output
> dir
> ├── a
> ├── b
> └── c
>
> The output refers to what?
> Or rather, Output refers to which command?
>
> So at the first line I would have liked to have the reference command,
> and then everything else.
>
> Example
>
> $ cat commands-output
> REFERENCE COMMAND: $ tree dir
> dir
> ├── a
> ├── b
> └── c
>
> It can be done?

(set -x; tree a) >commands-output 2>&1

Flash

unread,
Jul 1, 2022, 12:48:48 PMJul 1
to
Il 01/07/22 15:32, Joe Beanfish ha scritto:
> (set -x; tree a) >commands-output 2>&1

buona idea

Jasen Betts

unread,
Jul 1, 2022, 9:00:46 PMJul 1
to
On 2022-06-29, Java Jive <ja...@evij.com.invalid> wrote:

>> Now instead !! is not rightly evaluated.
>> Why?
>
> I've never used !! - following is a standard script header I use to
> have a script log itself. Of course this is just my choice from the
> possibilities, others may advise differently ...

Maybe it's just me but when I see !! I think of Lucky Luke.
https://www.youtube.com/watch?v=lv7RP4akiiw

--
Jasen.
Reply all
Reply to author
Forward
0 new messages