Comand Line, Linux vs Windows

If your not a computer geek you probably have never heard of Linux or have been told that its command line is powerful but difficult to use. However, I dont know much about Windows either, like did you know windows has a command line?. So without any further ado, let's get to the bottom of this.

Linux and Windows are 2 very different operating systems(OS). (I know there is mac too but I've heard its command line is similar to Linux so we'll leave that for another day)

Brief History

Microsoft Windows

First there was MS-DOS(Microsoft Disk Operating System) released in 1981. Then in 1983 Windows added a GUI(but left the COMMAND.COM command line for backwards compatibility).
DOS was set up to have one user per OS which proved to be less secure since it did not have the concept of access privileges. This was changed in the early 2000s with the Windows NT versions who abandoned parts of the DOS implementation and replaced it with a system that was more suited for multi user/session applications. However, initially it made no difference because the default user was the administrative(aka root) user which has all permissions. The Windows NT and later versions also had an improved command line called CMD(Command Prompt). But because it was still quite primitive, Microsoft eventually made a completely new shell released in 2006 called PowerShell. Nowadays(2025) windows comes with both CMD and PowerShell.

Linux

First there was Unix, first released in 1970 and later rewritten in C. Then The GNU Project developed a collection of free and open source software including a kernel base on Unix. The kernel was disliked but many of its other software packages live on to this day(the C compiler called GCC(GNU Compiler Collection), the bash shell, etc...). Then in the 1990s Linus Torvald made a better kernel called Linux(technically Linux is not an OS but only a kernel but commonly the word Linux refers to the Linux kernel plus GNU and other features). From there other companies and organizations made their own free and open source Linux distributions, among them: Debian, Red Hat, Ubuntu(based on Debian), Fedora(related to Red Hat), Oracle(based on Red Hat), etc...

Android

It's an OS based on Linux. It was developed primarily by Google and first released in 2008. This is why android phones come with Google play(nowadays however there are alternatives to the Google Play store like for example F-Droid)

macOS

It's a closed source OS based on Unix. First released in 1984 by NeXT, founded by Steve Jobs and later bought by Apple. Before this Apple devices were running Apple DOS.

Linux and Windows Main Differences

Versions and Updates

Windows is managed by one company which makes regular releases and then forces you to update next time you boot up your computer so that everything is pretty much the same for every user on the planet.
Linux on the other hand is made and updated by many different organizations, so you chose when and what you update. You chose what distribution you want(Debian, Ubuntu, etc...), what GUI you want(Xfce, GNOME, etc...) and what command line(aka shell) you want(Bash(usually the default), dash(sometimes aliased to sh), zsh, csh(seashell :) sorry lol C shell as in the programming language), fish, etc...) because there are several to chose from. This is why on the surface Linux seems more complicated because it's focused on accessibility and customizability instead of standardization for ease of use.

Overall Organization

On Linux:
Files and directories are organized in one big tree structure. There is a single root and everything branches off from there. When a USB or disk is mounted to the tree it just gets attached as a branch to whatever directory it is mounted in. You can mount the same device in several places at the same time. Learn more about how to mount USBs below

On Windows:
Files and directories are organized per drive and inside each drive you have a tree structure like in Linux. The C drive(denoted as C: ) is the main disk and it contains default programs, applications, system files and the OS itself. If you have extra storage disks(internal or external) or you plug in a USB or memory card on your computer then they will be named D:, E:, etc...
This means that you can not mount the same device in several places at the same time.

Files and File Types

On Linux:
Linux does not have a strict concept of file types. Everything is just a file, like even hardware(ex: keyboard, mouse, sound cards, etc...). And a file can have almost any name, you dont need to have the .something like in Windows. What the file is/does/is allowed to do is determined in the file permissions which is independent from the file extension.(To view file permissions of all files in the current directory type ls -l)(To change file permissions use the command chmod). The .somthing is only for better readability.
So often text files have .txt, executable files have .elf(Executable and Linkable Format), etc... but its not necessary.

Also, file names are case sensitive and you must NOT include spaces(cus otherwise you always need to use quotes which is annnnnoooooyyyyying)

On Windows:
In Windows instead of everything is a file its more like everything is an object. An object is a name plus an extension denoting what type of object it is. This is why Windows has strict file types. A file has a name and then a second field(separated by a dot) to denote the type of file.
here is a list of some common file type name extensions:
.txt is for text
.exe is for executable files
.bat is for batch files, a type of script file(a batch of instructions executed in order)

The file names can have spaces and are NOT case sensitive.

File Permissions and Ownership or Access Privileges

Usually there are 2 types of users:

On Linux:
Each file has file permissions which specify what the file can do depending on what user is using the file.

If you type ls -l every file in the current directory will be listed with its file permissions
The different parts of file permissions:
first char is what the file is(- for regular file, d for directory, etc...)
next 3 char specify if the user owner has r, w and/or x permissions(if do not have then it shows -)
next 3 char specify if the group owner has r, w and/or x permissions
next 3 char specify if others(not user or group owners) have r, w and/or x permissions
next comes the number of hard links
  ↪hard or soft links are similar to an alias but for files instead of commands(alias is a custom nickname of a command)
  ↪a hard link is a link to the physical memory storage of the content of the file(so by default all files have 1 hard link)
  ↪A soft link is a link to a file name
  ↪So, if you rename the file, the soft link still exists but is broken, while a hard link will still work
  ↪nb of hard links of directories is how many subdirectories it contains. An empty directory has 2(./ and ../)
  ↪you can create hard links with the command ln, and soft links with ln -s
next the name of the user owner is specified
next the name of the group owner is specified
next is the file size(in bytes)
next is the timestamp(last modified)
last but not least is the file name

If the special bits(s or t) are set then they replace the x when displaying the file permissions.

Root is not part of other users, root has all permissions and can freely change any file permissions.
Anyone can change file permissions of their own files using the command chmod, and only the root user can change file permissions of anyones file. The root user can also change the owner of a file.
Now a non root user can use sudo to run things as if they where root, but this only works if root has specified for the specific file/command that the user can use sudo without password to run it(there is a file called /etc/sudoers where sudo looks if it is allowed to run a file or if it has to ask for more permissions).

On Windows:
On Windows, for a long time this concept did not exist. But as mentioned earlier this security flaw has been fixed, sortof. Windows calls it access privileges because what a file can do is managed globally per user. To see the access privileges type whoami /priv in either CMD or PowerShell.
To see and or change the permissions of a specific file right click on the file in the file manager then go on properties and then to the security tab.
Notice a simple text file has all permissions(read, write, execute) both for the creator of the file as well as system wide! This is very different from Linux where files by default are never executable for security reasons.

Hardware Management and Audio Stuff

On Linux:
Note: Nowadays, some Linux distributions do like Windows and by default configure and mount everything for you but you can always configure it to be done manually because in Linux everything is just one tree which is helpful in server networks if you replace a server with its backup no one will notice and things go on smoothly(unlike windows where the discs are lettered by plugging in order so you would need an extra step to not have name mismatches). So for some practical and otherwise historical reasons Linux typically manually mounts its external hardware.

General hardware:
As mentioned earlier, in Linux everything is a file. When you plug in a device the device and your computer talk to each other. The device tells your computer what type of device it is so that the correct type of driver file can be created. Device files are stored in the /dev directory. You plug in a device via USB and a file is created, meaning the device and the computer talk even before you mount anything. If you plug in a mouse via USB, a file called mcelog is created. While if you plug in a USB stick, 2 files called sdb and sdb1 respectively are created(side note: sda is the internal storage hard drive of your computer and sda1, sda2, etc... are its different partitions. So sdb is the second detected storage device. Meaning if you plug in a second USB stick it would get the files sdc and sdc1).
Now pluging in a device just creates one or a few files in /dev. For some devices thats enough but for others like a USB stick you need to mount it. Mounting is the process of attaching the file tree structure of the usb stick to the computers file tree structure and establishing all the right permissions associated with that. This is why you dont need to mount a mouse in order to use it. Learn more about how to mount USBs below

Audio Specific:
The loud speakers and headset jack are internally connected so when you plug headphones in it automatically switches.
If you want to plug in a headset via USB with a USB adapter you have to go in your settings under audio mixer and change the settings there under playback. However, a video or other sound needs to be playing otherwise it does not show the needed settings.
Unlike Windows, Linux does not necessarily switch the audio card if you plug in a new device, taking a more configure things manually approach.

On the command line the commands pactl and pacmd, amixer can be used.

On Windows:
It's very similar to Linux just that the OS does all the configuration and mounting automatically for you, and instead of creating/loading a driver file it creates/loads a driver object. A driver is a program that acts as the middle man between hardware and the kernel.(So Windows is actually a self driving car lol and Linux is a manually controlled car, thats why it's called windows not window(windshield+ side and back windows) :) and your a passenger enjoying the view)
To see all your devices/currently active drivers use the device manager.

Unlike Linux, you just plug in your device via USB or headset jack and it automatically configures it for you and if necessary also mounts everything for you.

Several Simultaneous Logins

On Windows:
You can switch user without loging out the current user by doing Ctrl+Alt+Del.(VERY IMPORTANT: in Linux Ctrl+Alt+Delete is often configured to log out or in some cases even reboot the computer(if you are in a non-graphical interface(I talk about them just below) Ctrl+Alt+Delete will cause a reboot) so dont mix up the key combinations of Linux and Windows). But otherwise simultaneous logins are not easily doable in Windows, you need special software(Remote Desktop Protocol) to do remote login. Now PowerShell and CMD both support the ssh and scp Linux commands but they only work one way. You can ssh from Windows into a Linux device but you can not easily ssh from a Linux device into a Windows device without installing/configuring an ssh server on the Windows computer. Same goes for scp, you can run the scp command on Windows and copy from or to Linux but you can not run the command on Linux to copy to or from Windows.

On Linux:
In Linux on the other hand its easy because it was made to be multiuser right from the start. I explain how to use ssh and scp to login remotely into your computer from a different computer below.
But you can also login several times from your computer into your computer at the same time. This is done by doing:ctrl+alt+fn+f1(or ctrl+alt+f1 depending on your keyboard layout)
It is not a graphical user interface but otherwise its exactly like your computer. To switch back to your graphical user interface do: alt+fn+f7(or alt+f7 depending on your keyboard layout)
Now there are actually 5 more of these. So, there is f1 through f6 which are non-graphical(also called tty1-tty6) plus f7 being the graphical one). To switch between them just do ctrl+alt+fn+f(put nb here) if you are currently in the graphical UI and alt+fn+f(put nb here) if you are in a non-graphical UI.
The graphical interface has the added ctrl to avoid conflicting with user or application set key bindings. But in a non-graphical environment you wont have an application using the alt fn keys for something else so adding the ctrl to avoid confusion is not necessary.

Cross Compatibility Issue and Attempted Resolution

Compiled programs only run on the OS they have been compiled in because different OS have different system call conventions. As we have seen the whole setup of everything is totally different in these 2 operating systems so if you want cross compatibility you need some sort of translator.

To run Windows programs on Linux you serve wine :). lol no really a program called Wine will do the trick. Wine is not a virtual machine, it simply translates the system calls.

To have a bash shell(Linux shell) in Windows you can install wsl(Windows Subsystem for Linux).

To run Linux Programs on Windows that have a gui, I have not tried it but I heard that you can install wslg(Windows Subsystem for Linux GUI).

Command Line Commands and Basic Usage

In Linux open a shell(also called terminal)(the default is usually bash). In windows open CMD(Command Prompt) or PowerShell. (note: putty is not a shell. It's a way to ssh into a Linux device)

IMPORTANT: In Linux things are case sensitive unless specified. While in Windows things are not case sensitive unless specified.

Also, when wanting to specify a filename, if the file is not in the current directory then include path(can be relative or absolute).

If you are lost and confused about some of the concepts mentioned in the table(like aliases, command options, and how to get non mentioned details about specific commands) scroll down below the table for more explanation.

Commonly Used Comand Line Comands
comand description Linux(bash) Windows(cmd) Windows(PowerShell)
get manual page of a command man thing-you-want-manual-of help thing-you-want-manual-of get-help thing-you-want-manual-of
also aliased to help and man
print(aka list) content of current directory
list all files that contain xxx in the filename
list all files in a specified directory
ls
ls *xxx*
  • explanation: * means all

  • Linux is case sensitive

  • It also looks in subdirectories
ls path-to-directory
(can be relative or absolute)
  • dir also exists but uses a different listing format and style
dir
dir *xxx*
  • explanation: * means all

  • Windows is NOT case sensitive

  • It does NOT look in subdirectories
dir path-to-directory
(can be relative or absolute)
get-childitem
it is also aliased to dir, ls and gci
  • Works like dir in cmd
print lines matching given pattern
print lines containing xxx
print lines starting in xxx
grep pattern filename
grep xxx filename
grep ^xxx filename
  • if file not in current directory then include path(can be relative or absolute)
  • if dont want case sensitive: grep -i xxx filename
find "pattern" filename
or
findstr pattern filename
find "XXX" filename
or
findstr XXX filename
findstr /B XXX filename or findstr /b XXX filename
  • if file not in current directory then include path(can be relative or absolute)
  • if dont want case sensitive: findstr /i xxx filename
select-string "pattern" filename
WARNING: for pipeline does not print full line
need to use where-object instead
ex:alias | where-object {$_.name -like "XXX"}
the alias command lists all current aliases
select-string XXX filename
select-string ^XXX filename
or more filename | Where-Object { $_ -match "^xxx" }
  • if file not in current directory then include path(can be relative or absolute)
  • Not case sensitive
change directory

go to directory within current directory:
go to a completely different directory:
go up a directory:
go back to directory u where in before:
go to home directory:
go to root directory(in windows root directory is top of drive):
cd path-to-directory
use / to separate directory names
cd directoryname
cd /fullpath
cd ../ or cd ..
cd -
cd ~ or cd
cd /
The root directory is called /, this is why all directories that are directly in root start with /(ex: /tmp, /home, etc...)
cd path-to-directory
or chdir path-to-directory
use \ to separate directory names
cd directoryname
or chdir directoryname
cd \fullpath
or chdir \fullpath
cd ..\ or cd .. or chdir ..\ or chdir ..
there is no straight forward command
cmd does not keep a directory history like Linux bash
cd %homepath% or cd %HOMEPATH%
or chdir %homepath% or chdir %HOMEPATH%
cd \ or chdir \
set-location path-to-directory
also aliased to cd, chdir and sl
use \ to separate directory names
cd directoryname
cd \fullpath
cd ..\ or cd ..
there is no straight forward command
cd ~
cd \
print current directory's path pwd just type cd without anything else get-location
also aliased to pwd and gl
make directory mkdir directoryname mkdir directoryname
or md directoryname
mkdir directoryname
or md directoryname
copy cp file1 file2
  • here file1 is copied into file2
  • if file2 already exits it will ask if you want to overwrite
    (if say no it wont copy),
    otherwise it will create file2
    This is because cp by default is aliased to cp -ip which is an option to prompt user before overwriting(write which cp if you want proof)
  • if files are not in same directory then include path(can be relative or absolute)
copy file1 file2
  • here file1 is copied into file2
  • if file2 already exits it will ask if you want to overwrite
    (if say no it wont copy),
    otherwise it will create file2
    this is not because of aliases,
    in the help manual it says
    default behavior is to ask before overwriting unless copy is executed from a batch script
  • if files are not in same directory then include path(can be relative or absolute)
copy file1 file2
  • here file1 is copied into file2
  • It does NOT ask before overwriting
  • if files are not in same directory then include path(can be relative or absolute)
move or rename mv file1 file2
  • if you move file from one name to another name its like renaming
  • here file1 is moved into file2, so file1 will disappear and file2 is created
  • if file2 already exits it will ask if you want to overwrite
    if u say no it will not move the file
    This is because mv by default is aliased to mv -iv which is an option to prompt user before overwriting(write which mv if you want proof)
  • to move a file from one dir to another just include path(can be relative or absolute)
move file1 file2
  • if you move file from one name to another name its like renaming
  • here file1 is moved into file2, so file1 will disappear and file2 is created
  • if file2 already exits it will ask if you want to overwrite
    if u say no it will not move the file
    this is not because of aliases,
    in the help manual it says
    default behavior is to ask before overwriting unless move is executed from a batch script
  • to move a file from one dir to another just include path(can be relative or absolute)

ren file1 file2
  • works just like move but only for renaming
move file1 file2
  • if you move file from one name to another name its like renaming
  • here file1 is moved into file2, so file1 will disappear and file2 is created
  • if file2 already exits it will NOT let you move it
  • to move a file from one dir to another just include path(can be relative or absolute)

ren file1 file2
  • works just like move but only for renaming
remove/delete rm file-to-remove
rmdir directory-to-remove
  • it will not delete directory if not empty
del file-to-remove
rd directory-to-remove
  • it will not delete directory if not empty
remove-item file-or-directory-to-remove
Also aliased to del, erase, rd, ri, rm, rmdir
print something to screen echo characters-to-print echo characters-to-print echo characters-to-print
give absolute path
  • Often used to find out what the exact program/command is you are executing since aliases might have been used
list everything in the search path
  • you can only execute programs
    (without specifying full path) if they are in the search path.
    this is for safety
    so that if for example you download a malware program
    with a program called ls that actually does rm
    it will not run this program if you type ls
    but only if you give full path
which command-or-program-you-want-path-of
echo $PATH
  • to add something to the path its just like appending to any other variable, learn more about variables below
where command-or-program-you-want-path-of
echo %PATH%
  • to add something to the path its just like appending to any other variable, learn more about variables below
get-command command-or-program-you-want-path-of
$env:path
  • to add something to the path its just like appending to any other variable, learn more about variables below
display disk space usage info df -h wmic logicaldisk get Caption,FreeSpace,Size Get-WmiObject -Class Win32_LogicalDisk
more readable version:
Get-WmiObject -Class Win32_LogicalDisk |
Select-Object DeviceID, VolumeName, FileSystem,
@{Name='SizeGB'; Expression={[math]::Round($_.Size / 1GB, 2)}},
@{Name='FreeSpaceGB'; Expression={[math]::Round($_.FreeSpace / 1GB, 2)}},
@{Name='UsedSpaceGB'; Expression={[math]::Round(($_.Size - $_.FreeSpace) / 1GB, 2)}},
@{Name='PercentFree'; Expression={[math]::Round(($_.FreeSpace / $_.Size) * 100, 2)}},
@{Name='PercentUsed'; Expression={[math]::Round((($_.Size - $_.FreeSpace) / $_.Size) * 100, 2)}} |
Format-Table -AutoSize
login as different user(in the shell only)
login as root
su username
su root or su -
then it will ask for password of the root user
to logout write exit
  • the - means switch environment(aka fully become the new user not just switch id)
    This means change enviroment variables to be in accordance with the new user
    and go to the new users home directory
Not possible from the shell
(at least to my knowledge)
write cmd in the search bar at bottom left of screen,
below command prompt it shows several options one of which is run as admin
Not possible from the shell
(at least to my knowledge)
start wiriting powershell in the search bar at bottom left of screen,
below windows powershell it shows several options one of which is run as admin
run program as if you where root(but not logedin as root) sudo program-u-want-to-run
usually it will ask for password
(unless the rootuser has allowed it without)
runas /user:administrator nameofprocess
This will prompt for a password to allow admin privileges on this process
start-process nameofprocess -verb runas
This will prompt for a password to allow admin privileges on this process
print content of file one window size at a time more filename
  • use space bar to advance by one screensize

  • use enter to advance by one line

  • q to quit
less filename
  • like more but with more functionality(can go up or down line by line, better searching, etc...)

  • Faster than more and better for long files cus does not read entire file before starting
more filename
  • used like in Linux
more filename
  • used like in Linux
print the message buffer of the kernel, used for looking up what devices are connected to which ports dmesg wevtutil qe System /c:10 /f:text Get-WinEvent -LogName System -MaxEvents 10
print command line history history
This prints the last 1000 entered commands

on start up a shell gets the command history from the file ~/.bash_history and only writes to this file on exit. So the command history really shows the content of ~/.bash_history at the shells startup plus the current shells history.
cmd does not keep a history between sessions
for current session history: doskey /history
get-history or history
prints history of current session.
print also previous sessions history: Get-Content (Get-PSReadlineOption).HistorySavePath
print to file command-whos-output-you-write-to-file | tee filename
or echo "text to write to the file." | tee filename
or use redirection(see below table)
command-whos-output-you-write-to-file > filename
or echo "text to write to the file." > filename
command-whos-output-you-write-to-file | out-file -filepath filename
or "text to write to the file." | out-file -filepath filename
force a program/window to close (aka kill a program)
  • only do this if the program can not be quit/closed otherwise
    because this does not do all the cleanup that usually happens when closing
xkill
then select program to kill by clicking on it with the mouse
taskkill /PID the-pid-number
(you can get the PID using tasklist)
or taskkill /IM imagename-aka-programname-including-fileextention
stop-process -Name the-process-name or Stop-Process -Id the-pid-number
  • for process name no need for file extension
to see all running processes
print currently running processes started from this shell window
print processes with high CPU usage
ps -e or ps aux
(note: the command options of ps are a mixture of the BSD style(ps aux) which does not have a dash infront
and the newer unix style(ps -e)
I think ps aux and ps -aux do the same thing but I was told to not use it that way
ps or jobs
top
or ps -eo pid,cmd,etime,time,pcpu
tasklist
in theory you could filter the tasklist output to only show processes with the parent id of the current cmd but in practice you cant easily launch applications that have cmd as their parent because windows re-parents them to make them independent
tasklist /v /fi "cputime gt 00:01:40"
  • 100 seconds = 1 minute and 40 seconds where the 100 means total CPU time > 100 seconds
get-process
in theory you could filter the tasklist output to only show processes with the parent id of the current powershell but in practice you cant easily launch applications that have powershell as their parent because windows re-parents them to make them independent
Get-Process | Where-Object { $_.CPU -gt 100 } | Sort-Object CPU -Descending
  • the 100 means total CPU time > 100 seconds

Shells and How to Access Documentation

The words terminal, command line and shell are used interchangeably because for the user they are pretty much the same thing. Technically the shell is the software and the terminal is the thing displaying the output of the shell to the user but nowadays you cant really open a terminal without a shell running because the terminal automatically launches a shell(for Linux usually bash cus it's the default). And command line is the Windows term for both terminal and shell.
The name shell comes from the idea that you the user is on the outside, the kernel is on the inside and to access the kernel you have to go through the protective layer around the kernel, aka the shell.
The name terminal comes from the idea that the cables start at the computer and end aka terminate at the screen.

On Linux:
Linux has many different shells, but the most commonly used one is bash. Bash stands for Bourne again shell because it is a newer version of the Bourne shell. Also at the time the bourne shell was not open source so to have a shell that had the same/similar style and syntax as the bourne shell but have the same open source licence as Linux, bash was created.
To see what shell is your default type: echo $SHELL
reminder Linux commands are case sensitive so can NOT do: echo $shell
In this article we will focus on bash only.

In Linux the command man is used to access the manual page of a given command. However, some commands only have a help page(accessed by writing help command-name). The difference between help and man is that help is built into the specific shell you are using(so all built in commands like cd and alias have a help page and not a man page) while man is for getting documentation on programs which have each their own executable, meaning they also run exactly the same way in different shells.

In Linux the commands more and less are used to display man pages. So to learn how to navigate within a man page type: man less
If you type an incomplete command and then do tab twice it will display all commands that start with the letters you entered.

On Windows:
In Windows CMD the command help is used to access the manual page of a given command. Typing just help alone gives a list of all commands with a one line description.

Can I rant about PowerShell for a sec, who the hell came up with the idea of having commands be 2 words long?! Yes some of them have aliases but not enough of them. Also, the help files(accessed by typing help or get-help) give no good information, lots of pseudo examples but no word on what the command exactly does or what each option does. There is some documentation online(https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/) but I prefer having it locally in the shell.

alias

Alias is a command that allows the user to give a command a custom name. This is very practical if commands are long.
Also fun fact some common commands are aliased by default. Linux ex: ls is aliased to alias ls='ls --color=auto' because ls by default does not color code its output.
Aliases are only for the current session, if want them to be permanent need to add them to an alias file. Here is how to make temporary ones:

In Linux to create an alias do: alias aliasname='command' or alias aliasname="command"
to simply print exisiting aliases write alias without any arguments

In windows CMD:doskey aliasname=command
In windows PowerShell:set-alias -name aliasname -value command
to simply list currently existing aliases:
CMD: doskey /macros
CMD by default does not have any aliases.
PowerShell: type alias or get-alias

Command Options

To run a slightly different version of a command, command options are used.

WARNING: command options are not standardized, so they can vary from command to command. You can look up what the options for a specific command are in the manual (for Linux, in shell write:man commandname. for Windows, in shell write:help commandname).

Commonly Used Symbols and Operations Performed on Commands

&
Used in Linux to run process or command or application you are about to launch in the background. This allows you to keep using the command line for other things while the process or command or application is still running.
ex: nedit &
Note: when launching a browser from the command line it will look like the & did not work because lots of stuff is written on the screen and you dont get the prompt line back. However the & did work, you are able to type the next command you want or simply hit enter to get your usual prompt line back. The reason this happened is because the browser application still prints its standard output (stdout) and standard error (stderr) streams to the terminal even when backgrounded.

In Windows it is not necessary to specify that a process should run in the background because windows automatically reparents processes to make them independent.
However the & is used in CMD instead of a semicolon. And in PowerShell it is the call operator, used to execute a command that is stored in a string or a variable, or to execute a script or command with a path that contains spaces or other special characters.

Wild Cards

These characters can have different meaning depending on context(ex: * is used for both multiplication and as a wild card). For *, . and ? we will only cover what they mean in the context of specifying a search pattern.

*
It is used for filename expansion and means include all
It is the same for both Linux and Windows. ex: ls XXX*
here ls lists all files and directories inside current directory that start with XXX. If the star(aka asterisk) was not included(ls XXX) then it would look for exactly XXX and would not find XXXYZ.
ex2: ls XXX*.txt
this looks for files that start in XXX and end in .txt


. or ?
The particular character can be any character(like * but for a single character).
On Linux:
However, ? is used for filename extension since filenames often have .txt or .zip for example and we would not want to confuse that dot with a wild card. While . is used for grep and other commands where the search pattern is not necessarily a file(I have tried both . and ? for grep and so far they seem to both work).
ex:grep X.X filename
ex2: ls X?X.txt
On Windows:
For commands like dir only the ? works not the . on both PowerShell and CMD
for CMD findstr only the . seems to work
and for PowerShell where-object only ? seems to work

Redirection( > and >> )

In Linux bash and windows CMD:

ex: ls > myfile.txt
this will put the output of ls into the file called myfile.txt. If this file already exists it will overwrite.
ex2: ls >> myfile.txt
this appends to the file instead of overwriting.
Here we printed to the stdin stream of the command echo to a file. Putting 1 or 2 infront of > or >> will print the stdout or stderr respectively of the command to file.
For windows CMD its exactly the same.
For PowerShell the > and >> are the same aswell but instead of 3 output streams it has 6.

Pipeline( | )

Pipelines are used to be able to use different commands together.
They work from left to right, left most command is executed and its output is feed to the next command as input and so on.

example:
 ls | grep -i xxx
  here -i is a command option of grep that means not case sensitive.
  The command lists all file and directory names in the current directory that contain xxx in the filename(NOT case sensitive due to -i)
  here ls lists all files and directories in the current directory and feeds it as input to grep who then filters out all names that do not contain xxx
In Windows CMD and PowerShell the above example will work the same way, just replace ls with dir and grep with findstr for CMD and where-object for PowerShell
Both Linux and Windows PowerShell are built such that pretty much all commands either support pipe or can be used with other comands (like for Linux grep, xargs, sed, awk, regex etc... and for PowerShell where-object, select-object, select-string, regex, etc...) to support pipe. These commands convert the formating of other commands to allow pipelining but they can also be used as stand alone. The only difference in pipeing in Linux vs PowerShell is that Linux pipes pass text(through input output streams) while PowerShell passes object.
This is very different from CMD where only commands that support pipe can be used in pipelining(there are no conversion commands)

Scripts:Programming in the shell

We will only scratch the surface here because there is lots of amazing stuff to be learned here but this article would be to long.

On Linux:
Variables

Variables are denoted as: $myvariable, but only after declaration.
ex: i=5; echo $i
this will print: 5

If Statements

if [ condition ];
then
statement;
elif [ condition ];
then
statement;
else
statement;
fi

ex:i="4";j="4"; if [ "$i" == "$j" ]; then echo "bonjour"; else echo "hola"; fi
The space between if and [ and the spaces between [ and "$i" == "$j" and ] are important, if not included get syntax error. Also has to be [] not (). The quotes are not necessary here,
i=4;j=4; if [ $i == $j ]; then echo bonjour; else echo hola; fi
would also work

to have several conditions inside the same if do:
i=4;j=4;k=5; if [[ $i == $j && $j < $k ]]; then echo "bonjour"; else echo "hola"; fi

for numerical condition checks you should use two letter abbreviations instead of the traditional == or >=, etc...
ex: a=3; b=1; if [ $b -le $a ]; then echo yes; else echo no; fi
if you use == bash will let it slide but doing <= will give an error

meaning numbers strings
== -eq ==
!= -ne !=
< -lt ASCII letter by letter comparision
<= -le N/A
> -gt ASCII letter by letter comparision
>= -ge N/A

If you really want to use <= etc... for numbers, you can either use (()) instead of [] or [[]]
ex:a=3; b=1; if (( $b <= $a )); then echo yes; else echo no; fi
Or you can use the command let
ex: a=5; b=10; let "c= $a <= $b"; echo $c
here c will be 1(aka true)

For string comparision, == and != are used. < and > converts the strings to ASCII and comparess letter by letter. and <= and >= do not exist.

Loops
If you accidentally make an infinite loop press ctrl+c

For Loops:
ex1:for i in {1..5}; do echo "Iteration $i"; done
this counts up from 1 to 5
ex2:for i in {5..1}; do echo "Iteration $i"; done
this will count down.

While Loops:
ex:cnt=1; while [ $cnt -le 5 ]; do echo "count is $cnt"; ((cnt++)); done
VERY IMPORTANT: need to do ((cnt++)) NOT cnt++ because otherwise cnt will not be incremented resulting in an infinite loop. (stop the infinite loop using ctrl+c).

Until Loops:
Same but opposite of while. While runs as long as condition is true, until runs as long as condition is false.
ex:cnt=1; until [ $cnt -gt 5 ]; do echo "Count is $cnt"; ((cnt++)); done

Break and Continue:
Its just like most other programming languages
continue ex:for i in {1..10}; do if [ $i -eq 5 ]; then echo "half way"; continue; fi; echo "iteration $i";done
break ex:for i in {1..10}; do if [ $i -eq 5 ]; then echo "half way, lets take a break"; break; fi; echo "iteration $i";done

Comments and other useful things to know

If you start typing an if statement but dont type fi and hit enter, bash will show >
and let you continue typing until you end the if statement. Same goes for loops that dont have done at the end, or any other code that bash deams as unfinished.
This is useful because breaking your code into different lines can make your code more readable.

Comments are denoted as #
bash will ignore everything after that line even if you put ;

If you want to write your code/script in a separate file and then execute that file on the command line simply start your file with: #!/bin/bash
And once you are finished writing the script set the file to be executable using the chmod command.
If you want to use a different shell that is not bash then you would specify a different path, ex: #!/usr/bin/ctsh
To run the script simply write its name in the shell and hit enter.

On Windows:
In Windows scripts are called batch files and end in .bat
But like in Linux, you can do short scripts directly on the command line.
Variables

CMD ex:
set myvar=hello world & echo %myvar%
here the & acts as a semicolon.

PowerShell ex:
$myvar="hello world"; echo $myvar
In CMD the quotes would be included inside the string but in PowerShell they are needed here to not get an error.

If Statements

For CMD:
if condition (statement) else if condition (statement) else (statement)
If you do not want to use else if and else but just if alone then the statement does not need to be surrounded by ()
ex:set a=5
set b=5
if %a% equ 5 (echo great) else if %a%==%b% (echo amazing) else (echo ok)

CMD does not support arithmetics within the condition of the if statement so need to put the arithmetic into a variable first and then compare.
To have several conditions inside the same if do: if condition1 (if condition2 (statement)) else (statement)
ex: set myvar=hi
set c=8
if %myvar% equ hi (if %c%==8 (echo great)) else (echo ok)

For PowerShell:
if(condition){statment}elseif(condition){statment}else{statment}
There can't be a space between else and if, it needs to be elseif
ex:$myvar=123; $a=5
if($myvar -eq 123){echo "yippee"}elseif($a -ne 6){echo "yea"}else{echo "nope"}
you can easily do arithmetics in the if condition:
$a=1; $b=5;
if($a+$b -eq 6){echo "amazing"}
Note: it is not necessary to put a space before or after the -eq, I just like to do it for readability.
The ==, !=, etc... can not be used, only -eq and -ne respectively.
To have several conditions inside the same if do:
if($a -eq 1 -and $b -eq 5){echo "cool"}

meaning cmd powershell
== == or equ -eq
!= neq -ne
< lss -lt
<= leq -le
> gtr -gt
>= geq -ge
Loops
If you accidentally make an infinite look(lol loop :) ) press ctrl+c

For CMD:
The command for is used to do all the available loops.
ex: for /l %i in (1,1,5) do echo %i
here it counts up from 1 to 5.
ex2: for /l %i in (10,-2,1) do echo %i
here i counts down from 10 to 1 in steps of 2.
the /l tells it that (from, incrementor, to)
without the /l in ex1 i would have gotten the values 1,1 and 5.
for also has other command options like for example /f for file reading and writing where each file to iterate through is specified in the ()
write help for to see all the possible command options
break and continue: CMD does not have these features however goto can be used instead but it only works in batch files and not on CMD directly, see below.

For PowerShell:

Comments and other useful things to know

If you want to write your code/script in a separate file and then execute that file on the command line, write your code in a text editor like notepad. When saving the file call it mybatchfile.bat and select all files.
To run it simply cd to the directory where it is saved and write mybatchfile.bat
Important: since batch files can be run from both CMD and PowerShell, CMD syntax needs to be used.
ex using labels and an if statement:
@echo off
set i=1
:mylabel
echo hi from batch
echo wow
if %i%==1 (
set /a i+1
goto mylabel
)

The @echo off is so that it does not print every command as it executes it.

If you want to run commands that only exist in PowerShell inside a batch file need to add powershell.exe infront

comments:
CMD comments are rem or ::
ex:Echo hi &rem mycomment
Ex2: echo hi &:: mycomment
PowerShell comments are #
And multiline comments are<#mycomment#>

Other Useful Computer Things to Know

Commands Used When Several Devices Are Involved

Inorder for these commands to work the two devices need to be on the same network.

On Linux:

On Windows:
In the past CMD was not able to do ssh so PuTTY, a graphical ssh application had to be used.
When powershell came along Windows included ssh so nowadays both PowerShell and CMD can do it.
ssh and scp commands have the same syntax as in Linux. Just be careful: in Windows directory slashes are the other way around!!!

How to Use a USB in the Shell

On Linux:
Unless you have previously told your file manager not to, the file manager will do everything for you. But if you want to do it on the shell you can:
1)plug in USB
2)in shell write: dmesg
this will list the message buffer of the kernel. The last entry should be the device you just pluged in.
3)sudo mount device-name where-to-mount-it
ex:sudo mount /dev/sdb1 /mnt/usbka
The directory where to mount it should be an empty directory because if its not then you can not access the directories content until you unmount.
Sudo is used because you need to run the mount command as root.
dev is the directory where device files are stored. So when you plug the USB in, a file(called sdb1) is created for it in /dev
4)cd where-its-mounted
5)use the USB
6)cd out of the directory where the USB is mounted(otherwsie it will say USB is buissy so cant unmount)
7)sudo umount device-name
you can also do: sudo umount where-to-mount-it or sudo umount device-name where-to-mount-it
VERY IMPORTANT: always unmount USBs before unplugging because your computer does write caching to minimize delay. Meaning the computer does not necessarily fully write everything to the USB right away but only once it is not buissy doing other commands or if you unmount. It only guarantees that apon unmounting it will have writen everything.

Fun fact, you can mount a USB device in different directories at the same time. If you then do sudo umount device-name it will only unmount in one of the 2 directories so you have to do the command again to unmount in the other directory.
To see if device is still mounted do: mount | grep sdb

If you do not want to mount devices as root you can configure it such that you just write mount /mnt/usbka and it will know that you want to mount device /dev/sdb1. This configuration is done in a file called /etc/fstab


On Windows:
In windows there is no need to mount anything on the command line or otherwise because the OS should do it for you automatically.

How to compress(zip) files

Archiving is when you combine several files into one file(this is what the command tar does without command options).
Usually you also want to compress this archived file so it takes less space when you send it to someone(in Linux this is done with gzip(GNU zip, often abbreviated gz). The Linux tar command can use gzip to compress as part of its command options but tar and gzip are 2 different commands. While in Windows PowerShell the command compress-archive does both archiving and compression.
What happens when a file is compressed? Compression seems counterintuitive because you add more info(to decompress) to save space, like how should that work?. If you have a file where every single piece of both its data and metadata is totally different then compression wont work cus there is nothing that can be removed without losing info. But chances are there are patterns and repetition. ex: hello hello hello can be rewritten as XXX; X="hello"

comand description Linux Windows
zip
look at content without unzipping
to make sure content does not have same name as things already in directory
so u dont overwrite stuff
unzip/extract
zip zipfilename.zip foldername/*
unzip -l zipfilename.zip
unzip zipfilename.zip
  • in Linux its not a default command so need to install it
I could not find an equivalent for CMD.
In PowerShell:
compress-archive .\path\to\file1.txt, .\path\to\file2.txt .\path\to\archive.zip
add-type -assemblyname system.io.compression.filesystem
[system.io.compression.zipfile]:: openread("zipfilename.zip").entries

add-type stuff and [ststem. stuff] need to be on separate lines(so hit enter between typing the 2)
there is no need for a space between :: and openread but I put it here to better format this table
expand-archive -path zipfilename.zip
you can add -destinationpath if you want to extract it somewhere other than the current directory
tar gzip
look at content without unzipping
unzip/extract
tar -czvf zipname.tar.gz file-or-folder-to-zip
tar -tvf zipname.tar.gz
tar -xzvf zipname.tar.gz
where:
-c: Create archive
-z: Compress archive with gzip
-v: Display verbos/progress in the terminal while creating the archive
-f: Allows to specify filename of archive
-t:list content
-x:extract

  • It's native to Linux so unlike zip it has the option to keep file permissions and ownership info.
  • The ownership info will be overwritten if not extracting as root.
  • Preserving file permissions is essential because its what Linux is based on,
    if you want a file to stay read only for example
    or if the file should be executable you need the file permissions to allow that.
  • For files that where ziped in windows or with tools that do not preserve file permissions,
    the unzipping tool in Linux gives the file a set of default permissions set by the command umask
In the past this did not exist but now both cmd and powershell have tar.exe and the syntax is very similar to linux
you can write tar.exe or just tar
tar.exe acvf zipfilename.zip file-or-folder-to-zip
or
tar.exe cvfz zipfilename.zip file-or-folder-to-zip
tar tvf zipfilename.zip
tar xvf zipfilename.zip
where:
-a: auto compress
-c: Create
-z: Compress archive with specified extention
-v: Display verbos/progress in the terminal while creating the archive
-f: Allows to specify filename of archive
-t:list content
-x:extract

  • It keeps permissions but since windows does not handle permissions the same way as Linux this tar is not fully compatible with Linux file permissions

Keyboard Shortcuts

On Linux:
To see a list of all bash keyboard shortcuts: stty -a
↪ stty is a command that handles changing and printing terminal line settings
↪ To understand what the abbreviated meanings of the shortcuts mean in the stty -a printout, look in man stty(Note: interrupt means terminate process, and stop means suspend aka its still there but in the background)

There are also other shortcuts not on the stty -a list because they are dependent on the line editing style used. The default is emacs style but vim style also exists. The below table does not include these shortcuts.

On Windows:
I was not able to find a good way to view CMD keyboard short cuts. PowerShell on the other hand for once has good documentation.
To see a list of all PowerShell keyboard shortcuts with a small description: Get-PSReadLineKeyHandler

Some of many useful keyboard shortcuts
Shortcut in general
(same for both Linux and Windows)
Linux bash CMD and PowerShell
Ctrl+c copy smoothly stop the current running program from this command line
(if did not put & behind when launching)
ctrl+\ hard stops the current running program from this comand line
Copy selected text. If nothing is selected, smoothly stop the current command
Ctrl+v paste -take next character as is/literally(not as a command)
-ex: ctrl+v then if do ctrl+c it will show ^C(meaning ctrl+c) in the input field
instead of executing the ctrl+c command of smoothly stopping a program
paste
Ctrl+z undo suspend
aka send current running program to background
in cmd:Marks the end of a line (text after this is ignored)
in powershell:undo
Ctrl+y redo N/A cmd:N/A
powershell:redo
Ctrl+x cut N/A N/A
Ctrl+u opens the source code of a website erases everything from the current cursor position to the beginning of the line N/A
Ctrl+a select all move cursor to the beginning of the line cmd:select all
Powershell:select the current line
Ctrl+e N/A move cursor to the end of the line N/A
Ctrl+s save stop showing what is being typed
-it is stored in a buffer im assuming
since crtl+q makes what you are typing and have typed after ctrl+s appear
-during ctrl+s you cant execute commands
but once you type ctrl+q it resumes
so if you have a finished command typed out it will immediately execute it
cmd:N/A
PowerShell: open forward search history
Ctrl+Shift+t reopen previous tab in a browser
Ctrl t: open a new tab in a browser
open new tab N/A
Ctrl+Alt+select with the mouse select only specific columns of a table on a webpage N/A N/A
up and down arrow keys scroll up or down in a browser scroll through command history scroll through command history
Ctrl+r reload the current webpage in a browser. open the search command history prompt cmd:N/A
powershell:open reverse search history
Ctrl+o open a file in a browser like enter, it executes the typed(or if in search history mode, the selected) command N/A
Ctrl+f open the search bar N/A cmd:open the search bar
powershell:N/A
Ctrl+g open the search bar,
if already open then go to next instance of search pattern
Leave the search command history prompt without executing a command N/A

References


Back to building blog

Copyright © 2024-2025 Jessica Socher ()