2

I am trying to run a Bash command where an alias exists in PowerShell Core.

I want to clear the bash history. Example code below:

# Launch PowerShell core on Linux
pwsh

# Attempt 1
history -c
Get-History: Missing an argument for parameter 'Count'. Specify a parameter of type 'System.Int32' and try again.

# Attempt 2
bash history -c
/usr/bin/bash: history: No such file or directory

# Attempt 3
& "history -c"
&: The term 'history -c' is not recognized as the name of a cmdlet, function, script file, or operable program.

It seems the issue is related to history being an alias for Get-History - is there a way to run Bash commands in PowerShell core with an alias?

user9924807
  • 707
  • 5
  • 22
  • 1
    I think you want `bash -c history -c` – briantist Sep 07 '21 at 16:30
  • 1
    @briantist, our wires had crossed in answering (you were first); syntactically, it would have to be `bash -c 'history -c'` (single `-c` argument), but with this particular command it doesn't actually work. I've also added some more info about Bash's CLI to the answer. – mklement0 Sep 07 '21 at 17:25

1 Answers1

3
  • history is a Bash builtin, i.e. an internal command that can only be invoked from inside a Bash session; thus, by definition you cannot invoke it directly from PowerShell.

  • In PowerShell history is an alias of PowerShell's own Get-History cmdlet, where -c references the -Count parameter, which requires an argument (the number of history entries to retrieve).

    • Unfortunately, Clear-History is not enough to clear PowerShell's session history as of PowerShell 7.2, because it only clear's one history (PowerShell's own), not also the one provided by the PSReadLine module used for command-line editing by default - see this answer.

Your attempt to call bash explicitly with your command - bash history -c - is syntactically flawed (see bottom section).

However, even fixing the syntax problem - bash -c 'history -c' - does not clear Bash's history - it seemingly has no effect (and adding the -i option doesn't help) - I don't know why.

The workaround is to remove the file that underlies Bash's (persisted) command history directly:

if (Test-Path $HOME\.bash_history) { Remove-Item -Force $HOME\.bash_history }

To answer the general question implied by the post's title:

To pass a command with arguments to bash for execution, pass it to bash -c, as a single string; e.g.:

bash -c 'date +%s'

Without -c, the first argument would be interpreted as the name or path of a script file.

Note that any additional arguments following the first -c argument would become the arguments to the first argument; that is, the first argument acts as a mini-script that can receive arguments the way scripts usually do, via $1, ...:

# Note: the second argument, "-", becomes $0 in Bash terms,
#       i.e. the name of the script
PS> bash -c 'echo $0; echo arg count: $#' self one two
self
arg count: 2
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • As you noted, bash -c ‘history -c’ does not work. Also, creating env variables using bash -c ‘export test=123’ has no effect. Any idea why that is? Can’t find alternatives online. – user9924807 Sep 08 '21 at 09:28
  • 1
    @user9924807, any external program you run from PowerShell (or any shell, for that matter) of necessity runs in a _child process_. Therefore, any environment variable you set in that chid process is limited to that child process (and any of its children) - PowerShell never see it. If you want to set an environment variable for the current PowerShell session, use `$env:test = '123'` – mklement0 Sep 08 '21 at 12:32