Equivalent for linux mkdir {fileA,fileB} in PowerShell - powershell

I'm just curios. Is there an equivalent for PowerShell that behaves equally to the liunx command listed in the title, i.e.
mkdir {folderA, folderB}
?
-- edit
the command listed above creates the folders "folderA" and "folderB" (just saw that I wrote file previously. Sorry, my fault) in the current working directory.

The mkdir command in PowerShell is a wrapper for the New-Item command. If you want to create multiple folders with a single command, then run:
mkdir c:\test,c:\test2;
Effectively, because of positional parameters in PowerShell, this passes the array c:\test,c:\test2 to the -Path parameter of the New-Item command.

Related

Perl: List files and directories recursively but exclude some directories and files that passed

Please give any suggestion or snippet or anything that may work.
I have already tried wanted function but how do I exclude some directory while recursing?
In Linux, you can make use of the Linux "find" and "grep" commands and run those Linux commands in Perl using qx to store Linux command result in Perl.
e.g.
$cmd = "find . | grep -v 'dir1\|dir2\|...\|dirn'";
$result=qx($cmd);
The above command combinations do the following:
The find command will list the all the directory and
files recursively.
The pipe "|" will pass the find result to grep command
The grep -v command will print on screen only the string not exist
in the "dir1", "dir2"..."dirn" to be ignored
At last, the qx command will execute the find and grep Linux
commands and stored the output to $result variable.
You can do the similar thing in Windows. The only difference is to use the Windows command line.
e.g.
$result=qx('dir /b/s | find /v "workspace" | find /v "TVM"')
The above command will list all the directory recursively except the directory has name "workspace" or "TVM".

ssh-keygen: The System Cannot Find the Path Specified

ssh-agent, ssh-add all works on Cmder running PowerShell/Posh-Git
I have added C:\Program Files\Git\usr\bin Environment Variables
ssh-keyen works fine on Git Bash,
how can I make ssh-keygen to also work with Powershell/Posh-Git ?
EDIT:
It turns out that the error is due to the fact that ssh-keygen in PowerShell is running the ssh-keygen.bat file instead of ssh-keygen.exe
So setting an alias as mention below is the way to go.
I use Set-Alias instead of New-Alias because New-Alias requires me to reset my $profile every now and then, which is weird.
To reset, type . $profile
One way to do this is to add it to your path.
Unfortunately, there appears to be no way to add only the executable. In other words, you will be required to add the whole bin folder (namely C:\Program Files\Git\usr\bin) to your path.
I can show you how to add the whole directory to the path, but I don't think this is what you want. Instead, below is an alternative method that only adds the ssh-keygen.exe executable.
Navigate to $env:homepath\Documents\WindowsPowerShell (create it if you don't have it).
Create a file called profile.ps1.
Add to the file the following line of code.
New-Alias Ssh-Keygen "C:\Program Files\Git\usr\bin\ssh-keygen.exe"
Now, each time you launch Powershell, Ssh-Keygen will be available. It even works with tab completion (e.g. type ssh- and press tab, then it automatically becomes Ssh-Keygen).
Actually, you can add single executables from the git bin folder to your path by symlinking them into a folder that is contained in your path variable.
I also wanted to use some of the git tools inside powershell but I didn't want to load the git-bin-folder into path every time I wanted to use one of the tools and I also didn't want to overwrite tools like cp, find, ls and so on...
Create a folder that you can add to path. I created mine in C:\dev\bin and added it to the path variable.
Then you need to symlink all the dll-files from the git bin folder to your new bin folder because the tools you'll link need them in the same directory (the runpath won't be the git-bin-dir but the new bin-dir). I'll add a Script to do that below.
And finally you just need to create symlinks for all tools you'd like to use in powershell as well (hint: ssh.exe is really nice to use in powershell ;))
Here are my powershell functions that'll help you set up your new bin-folder with all the nice tools from git:
# generic symlink function
function Create-Symlink {
param(
[string]$link,
[string]$target
)
& cmd.exe /c mklink "$link" "$target"
}
# symlink all teh git dlls
function Create-GitDllSymlinks {
param(
[string]$newBinDir='C:\dev\bin',
[string]$gitBinDir='C:\Program Files (x86)\Git\bin'
)
$dlls = gci $gitBinDir -Filter *.dll
$dlls | foreach {
Create-Symlink -link (join-path $newBinDir $_.Name) -target $_.FullName
}
}
# to easily link your git tools
function Create-GitSymlink {
param(
[string]$executable,
[string]$newBinDir='C:\dev\bin',
[string]$gitBinDir='C:\Program Files (x86)\Git\bin'
)
if (-not $executable.EndsWith('.exe')) {
$executable = ($executable + '.exe')
}
Create-Symlink -link (join-path $newBinDir $executable) -target (join-path $gitBinDir $executable)
}
# create all dll symlinks needed
Create-GitDllSymlinks
# link ssh and ssh-keygen to use in powershell
Create-GitSymlink -executable ssh-keygen
Create-GitSymlink -executable ssh
Another nice thing to do is this:
create a bash.bat file in your new bin-folder
write this into that .bat file:
"C:\Program Files (x86)\Git\bin\sh.exe" --login -i
quickly switch between powershell and bash:
when in powershell, type bash and git-bash will start inside the same window with access to all git tools in the git-bin-folder.
want to go back to powershell? just type exit!
Edit:
I reinstalled my computer a few days ago (with Win 10) and ran into some issues with my solution above. Apparently, git and/or the cygwin environment in git has been updated and the cygwin applications now search for their unix-environment-paths differently.
For example, ssh always said that it couldn't find my home path:
Could not create directory '/home/myuser/.ssh'.
The authenticity of host 'hostx (IP)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxx.
Are you sure you want to continue connecting (yes/no)?
Using procmon I found out, that it was looking for files in c:\etc and c:\home\myuser. Setting environment variables like HOME or USERPROFILE didn't work, so I just made two additional symlinks to satisfy my cygwin tools:
PS bin # cmd /c mklink /D C:\etc "C:\Program Files\Git\etc"
symbolic link created for C:\etc <<===>> C:\Program Files\Git\etc
PS bin # cmd /c mklink /D C:\home "C:\Users"
symbolic link created for C:\home <<===>> C:\Users
I solved the problem by generating my own ssh key pair using command
$ ssh-keygen -t rsa -C "your_email#mail.com"
in powershell. If you already have a SSH key, then don't a generate new key, as they will be overwritten. You can use ssh-keygen command, only if you have installed Git with Git Bash.
When you run the above command, it will create 2 files in the ~/.ssh directory.
~/.ssh/id_rsa − It is private key or identification key.
~/.ssh/id_rsa.pub − public key
See link generate ssh key

Compressing to tar.xz using 7-zip through a pipe on windows

My command line is this (powershell):
$7z ="`"c:\Program Files\7-Zip\7z.exe`""
&$7z a -r -ttar -bd -so . | &$7z a -r -txz -bd $archive -si
The produced archive file indeed contains a tar file, but that tar file is corrupt.
Note, that breaking the pipe into two commands works correctly:
&$7z a -r -ttar -bd ${archive}.tmp .
&$7z a -r -txz -bd $archive ${archive}.tmp
The produced archive is perfectly valid.
So, what is wrong with my pipeline?
(I am using Powershell)
Nothing is wrong with your pipeline it is the way that the pipeline works that's causing the error.
PowerShell pipe works in an asynchronous way. Meaning that output of the first command is available to the second command immediately one object at the time even if the first one has not finished executing, See here.
Both Unix and PowerShell pipes operate in the same way. The reason why you might be seeing a difference from Unix to PowerShell is the way in which they go about it is different.
Unix passes Strings between the commands. Where as a Powershell pipe will pass full-fledged .net object between commands. This difference in the data type being past between command will be why it works on unix and not in PowerShell. If 7z.exe can not huddle these .net objects correctly the files will be come corrupt, See here.
Try adding | %{ "$_" } in between the pipes like
&$7z a -r -ttar -bd -so . | %{ "$_" } | &$7z a -r -txz -bd $archive -si
The point is that the second call to 7z expects unmodified data on STDIN, but PowerShell is converting the output from the first call to 7z to (multiple) (string) objects. % is an alias for foreach-object, so what the additional command does is to loop over each object and convert it to a plain string before passing it on to the second call to 7z.
Edit: Reading through PowerShell’s Object Pipeline Corrupts Piped Binary Data it looks to me now as if my suggestion would not work, and there's also no way to fix it. Well, other than wrapping the whole pipeline into a cmd /c "..." call to make cmd and not PowerShell handle the pipeline.
Edit2: I also was trying this solution from the PowerShell Cookbook, but it was very slow.
In the end, I created a .cmd script with the 7z pipes that I'm calling from my PowerShell script.

How do I change directory and run a file in that directory in powershell?

For example, i want to run cygwin.bat which is located in the c:/cygwin/ directory...
I tried the following but got an error:
cd c:/cygwin ./cygwin.bat
cd c:/cygwin and ./cygwin.bat are two different statements. You can execute them from the interactive console like so:
PS C:\> cd c:/cygwin
PS C:\cygwin> ./cygwin.bat
Or, if you really want to do it on the same line, then use a ; between them to indicate separate statements.
cd c:/cygwin ; ./cygwin.bat
best way is the way its always been
c:\cygwin\cygwin.bat
it's all you need to type
Try iex
$command = "cd c:/cywin"
iex $command

Difference between mkdir and mkdir -p?

I've been following Learn Code the Hard Way's tutorial on learning how to utilize the command line interface in PowerShell. In this article, it tells me to use the command mkdir -p i\like\icecream. At the bottom, it explains "mkdir -p will make an entire path even if all the directories don't exist."
I'm confused, as mkdir i\like\icecream without the -p argument still does the same thing. I've experimented and done stuff such as creating a "one" directory, then creating "one\two\three" with mkdir and it will automatically create a two directory for three to be placed in. Does PowerShell automatically assume -p or something in cases like this? I'm at a loss as to what this argument does.
PowerShell does its best to determine what parameter you mean even if you don't give it fully. Thus if you use the -p parameter, you are actually using -path.
For the mkdir function, the -path parameter tells the function the path to create. -path is also by default the first argument to the function if no explicit parameters are provided. So calling the function with -p (-path) and without -p are exactly the same thing as far as the function is concerned.
For more information, in the shell type:
Get-Help mkdir
I will also clarify that when you call mkdir, what you are really doing is calling the New-Item cmdlet and specifying the -ItemType parameter as Directory. That is why you see the New-Item help when you run that command. If you want to see the actual code for the mkdir function to see how it does this, do this:
(get-command mkdir).ScriptBlock
If we create a directory using,
mkdir, mkdir will throw an exception if the directory already exists,so we need to check
before creating a directory over same path
whereas
mkdirp, mkdirp always checks automatically if the directory exists or not over the
specified path, hence no need to implement any check.