Bash Index : C - The 'C' Bash commands : description, flags and examples

mail

chcon

Usage

change file's SELinux security context

Flags

Flag Usage
-R --recursive operate on files and directories recursively
-t type --type=type set type type in the target security context
-v --verbose output a diagnostic for every file processed

Example

make files readable by Apache (details) :

chcon -Rt httpd_sys_content_t /data

mail

chage

Usage

change user password expiry information
Except for the -l option, chage is restricted to .

Flags

Flag Usage
-E expireDate
--expiredate expireDate
Set the date on which the user's account will no longer be accessible (i.e. account will be locked) :
  • as a date in YYYY-MM-DD format
  • or as the number of days since January 1, 1970. -1 removes the account expiration date
A user whose account is locked must contact the system administrator before being able to use the system again.
-l --list Show account aging information (human-friendly version of passwd -S)

Example

Let's experiment :

  1. create a user account :
    adduser bob
  2. get account initial information :
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash			a password is set
    /etc/shadow:bob:$6$f9YcHiE8Fc5Ho4Z4bALVuc/:18535:0:99999:7:::	the encrypted password
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  3. lock the password with passwd :
    passwd: password expiry information changed.
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash
    /etc/shadow:bob:!$6$f9YcHiE8Fc5Hxdvk$YW1TwjbGerIKvp8vY.rRPBESiIduTOI8.eDzTWjQZyhPMTd6SMl2Ju21dDvEJLTFjeru2YEaWa7o4Z4bALVuc/:18535:0:99999:7:::
    bob L 09/30/2020 0 99999 7 -1
    chage -l bob
    (same as above)
  4. lock the password with passwd :
    passwd: password expiry information changed.
    grep bob /etc/{passwd,shadow}
    /etc/passwd:bob:x:1001:1001:,,,:/home/bob:/bin/bash
    /etc/shadow:bob:$6$f9YcHiE8Fc5Hxdvk$YW1TwjbGerIKvp8vY.rRPBESiIduTOI8.eDzTWjQZyhPMTd6SMl2Ju21dDvEJLTFjeru2YEaWa7o4Z4bALVuc/:18535:0:99999:7:::
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    (same as above)
  5. expire the account with usermod :
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : Jan 02, 1970
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  6. un-expire the account with usermod :
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  7. expire the account with chage :
    chage -E 1 bob
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : Jan 02, 1970
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  8. un-expire the account with chage :
    chage -E -1 bob
    (returns nothing)
    bob P 09/30/2020 0 99999 7 -1
    chage -l bob
    Last password change                                    : Sep 30, 2020
    Password expires                                        : never
    Password inactive                                       : never
    Account expires                                         : never
    Minimum number of days between password change          : 0
    Maximum number of days between password change          : 99999
    Number of days of warning before password expires       : 7
  9. delete the user account :
    userdel -r bob

To "unexpire" a password (source) :

chage stuart
Changing the aging information for stuart
Enter the new value, or press ENTER for the default

	Minimum Password Age [0]: 
	Maximum Password Age [99999]: 
	Last Password Change (YYYY-MM-DD) [2018-06-08]: 
	Password Expiration Warning [7]: 
	Password Inactive [-1]: 
	Account Expiration Date (YYYY-MM-DD) [1970-01-02]: -1
mail

chpasswd

Usage

update passwords non-interactively

Example

echo bob:password | chpasswd
mail

cd

Usage

change directory, i.e. move into another directory

cd has some default behaviors :

Command ... Is interpreted as ... Comments
cd cd $HOME
cd - cd "$OLDPWD" && pwd If you don't want the original directory name to be displayed, use cd "$OLDPWD" instead of cd -
mail

comm

Usage

comm [options] file1 file2

To find lines common to 2 files :
  1. sort file contents
  2. remove duplicates
  3. comm -12 file1 file2

Flags

Flag Usage
-1 suppress column 1, i.e. display lines unique to file2 and common lines
-2 suppress column 2, i.e. display lines unique to file1 and common lines
-3 suppress column 3, i.e. display lines unique to file1 and lines unique to file2 (i.e. hide common lines)

Example

Trying all -1, -2 and -3 options at once :

tmpFile1=$(mktemp); tmpFile2=$(mktemp); echo 'FILE1' > "$tmpFile1"; echo 'FILE2' > "$tmpFile2"; for i in {1..3}; do echo "line $i" >> "$tmpFile1"; done; for i in {3..5}; do echo "line $i" >> "$tmpFile2"; done; cat "$tmpFile1" "$tmpFile2"; for mode in 1 2 3 12; do echo -e "\n'-$mode' mode :"; comm -$mode "$tmpFile1" "$tmpFile2"; done; rm "$tmpFile1" "$tmpFile2"

FILE1			result of cat file1 file2
line 1
line 2
line 3
FILE2
line 3
line 4
line 5

'-1' mode :
FILE2
	line 3		this line is common to both files, others are unique to file2
line 4
line 5

'-2' mode :
FILE1
line 1
line 2
	line 3		this line is common to both files, others are unique to file1

'-3' mode :		common lines are hidden
FILE1
	FILE2
line 1
line 2
	line 4
	line 5

'-12' mode :		displaying only common lines
line 3
mail

cruft

Usage

Cruft is a Debianoid tool to look over your system : It is available as package cruft in the Debian archive.

Flags

Flag Usage
-r reportFile Output report to reportFile instead of standard output.
this option is recommended since output can be VERY verbose
mail

chmod

Usage

change file mode bits (i.e. permissions)

Privileges required to run chmod :

chmod can only be executed by (source) :

chmod has the X flag for setting the executable bit only on directories :

mkdir dir; touch file; ls -l
drwx------ 2 bob developers 4096 Mar 23 16:35 dir
-rw------- 1 bob developers    0 Mar 23 16:35 file
chmod a+X *; ls -l
drwx--x--x 2 bob developers 4096 Mar 23 16:35 dir
-rw------- 1 bob developers    0 Mar 23 16:35 file

Different ways to specify file permissions :

Flags

Flag Usage
-R --recursive change files and directories recursively
--reference=referenceFile apply permissions like those of referenceFile (see also chown's --reference)

Example

testFile=$(mktemp --tmpdir playingWithFilePermissions.XXXXXXXX); ls -l "$testFile"; chmod o=wr "$testFile"; ls -l "$testFile"; chmod o-w+x "$testFile"; ls -l "$testFile"; chmod 777 "$testFile"; ls -l "$testFile"; chmod g=--- "$testFile"; ls -l "$testFile"; rm "$testFile"

-rw------- 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		default permissions for new file
-rw----rw- 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod o=rw
-rw----r-x 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod o-w+x
-rwxrwxrwx 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod 777
-rwx---rwx 1 stuart users 0 Mar	8 16:41 /tmp/playingWithFilePermissions.50YC1hqb		made by chmod g=---
mail

chroot

Usage

run command or interactive shell with special root directory "/". Once done, leave with exit.

This command allow many hacks. One of them is changing a user's password while running a machine in "rescue" mode.
In such mode, after the machine has been rebooted via a "Live CD" (or anything similar), its "/" filesystem is mounted as /mnt/something. There are situations where you need to change a user (or ) password, then boot the server normally and log in (with password, since SSH keys are not available...) to investigate.

To do so (as in rescue mode) :
  1. chroot /mnt/something
  2. passwd
  3. reboot in normal mode
  4. log in as with the password you've just set
  5. debug / fix what needs to be debugged / fixed
  6. don't forget to restore the account to its initial state, or at least to lock it.
mail

cryptsetup

Usage

Setup cryptographic volumes for dm-crypt

Flags

Flag Usage
-c cipher --cipher cipher Use the cipher encryption algorithm
-h hashingAlgorithm --hash hashingAlgorithm use hashingAlgorithm for passphrase hashing
-s numBits --key-size numBits use a numBits bits long key

Example

cryptsetup luksFormat
set up a new dm-crypt device in LUKS encryption mode
cryptsetup luksOpen
open an existing dm-crypt device
cryptsetup luksClose
close a dm-crypt device
cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       753287 iterations per second
PBKDF2-sha256     407055 iterations per second
PBKDF2-sha512     324435 iterations per second
PBKDF2-ripemd160  512000 iterations per second
PBKDF2-whirlpool  158299 iterations per second
#  Algorithm | Key |  Encryption |  Decryption
     aes-cbc   128b   167.4 MiB/s   187.6 MiB/s
 serpent-cbc   128b    74.9 MiB/s   213.3 MiB/s
 twofish-cbc   128b   179.5 MiB/s   236.5 MiB/s
     aes-cbc   256b   129.2 MiB/s   141.6 MiB/s
 serpent-cbc   256b    85.6 MiB/s   215.2 MiB/s
 twofish-cbc   256b   185.8 MiB/s   233.7 MiB/s
     aes-xts   256b   175.6 MiB/s   182.9 MiB/s
 serpent-xts   256b   196.6 MiB/s   199.1 MiB/s
 twofish-xts   256b   216.0 MiB/s   215.0 MiB/s
     aes-xts   512b   134.8 MiB/s   136.1 MiB/s
 serpent-xts   512b   195.7 MiB/s   199.9 MiB/s
 twofish-xts   512b   216.5 MiB/s   214.0 MiB/s

http://security.stackexchange.com/questions/40208/recommended-options-for-luks-cryptsetup
	For actual encryption, you will want XTS, which has been designed to support disk encryption efficiently.

http://security.stackexchange.com/questions/5158/for-luks-the-most-preferable-and-safest-cipher
	- In terms of the cipher alone, Serpent is generally agreed upon to be the most secure common cipher for LUKS.
	- (...) assuming you don't have national secrets or sensitive corporate data on your PC, AES-XTS-PLAIN is expected to be resistant for a reasonable timeframe against an attacker.

	==> serpent-xts-256 ?


https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
mail

cat

Usage

man cat says concatenate files and print on the standard output. This utility actually has more usages :
  1. effectively concatenate files : cat file1 file2 file3 > resultFile
  2. quickly display the contents of a single file : cat someFile
    this proves useful only when someFile is shorter than the number of lines your terminal can display. Otherwise, you'll only see the yourTerminalHeight trailing lines of someFile. In such case, less, head or tail might be good candidates.

    Please, please, PLEASE, don't fall in the useless-uses-of-cat n00b-trap !

  3. output several lines of text using heredocs
  4. "burn" the contents of an .iso image onto a USB key / storage card to boot from and install a new operating system

Useless use of cat (aka UUOC) :

We ALL did it, but now, the cat | construct should ring the bell of uselessness and waste of resources (even though modern computers have so much CPUs and GB of RAM to waste that such commands will pass unsuspected ).

Actually, any extra | induces an additional process fork, which is an expensive CPU-time operation (especially on loops). Moreover, cat someFile | reads the whole file before piping it to the 2nd command, which delays its execution for big files.

Usage DON'T DO
View the contents of file, which is longer that your terminal height cat file | less less file
View the lines of file matching pattern cat file | grep pattern
cat file | head pattern
cat file | tail pattern
grep pattern file
head pattern file
tail pattern file
Read file line by line cat file | while read line; do echo $line; done while read line; do echo $line; done < file
Alter the lines of file matching pattern cat file | awk '/pattern/ {doSomething}'
cat file | sed 'sed' options
awk '/pattern/ {doSomething}' file
sed 'sed' options file
Extract a field (i.e. a column) from file cat file | cut 'cut' options cut 'cut' options file

Flags

Flag Usage
-n --number number all output lines
mail

cp

Usage

Copy files and directories
By default, cp silently overwrites existing files (details).

Flags

Flag Usage
-a --archive same as -dR --preserve=all
=	-d					-R	--preserve=all
=	--no-dereference --preserve=links	-R	--preserve=all
=	--no-dereference -R --preserve=all
To copy the full contents of a directory, as is, into another :
cp -av sourceDir/* destinationDir
--backup[=backupOption] Instead of overwriting the destination file, make it a "backup" copy. The behavior depends on the value of backupOption :
  • (none) : make simple backups (i.e. only 1 backup, with either the default or the specified suffix)
    -b is equivalent to --backup with no backupOption
  • none, off : never make backups
  • numbered, t : make numbered backups. Will create 1 new backup every time, with incrementing suffix : .~1~, .~2~, ...
  • ...
see examples
-d same as --no-dereference --preserve=links
-f --force (details)
-n --no-clobber this flag causes a warning :
cp: warning: behavior of -n is non-portable and may change in future; use --update=none instead
-P --no-dereference never follow symbolic links in sourceDir (i.e. copy the link, not its target)
-p --preserve preserve default attributes
--preserve=attributeList preserve the attributes specified with attributeList :
  • default attributes : mode, ownership, timestamps
  • additional attributes : context, links, xattr, all
-R -r --recursive copy directories recursively
-S suffix --suffix=suffix set the backup suffix (default : ~). works only with simple backups see examples
-s --symbolic-link make a symbolic link instead of copying. These commands are equivalent :
  • cp -s regularFile resultingSymlink
  • ln -s regularFile resultingSymlink
--update[=updateOption] control which existing files are updated based on updateOption : all, none, older (default)
-v --verbose explain what is being done

More about cp -f :

man cp says : if an existing destination file cannot be opened, remove it and try again (this option is ignored when the -n option is also used)
The final part (between parenthesis) is clear (-n disables -f), so let's concentrate on the beginning :

if an existing destination file cannot be opened, remove it and try again

man cp says : If a file descriptor for a destination file cannot be obtained, attempt to unlink the destination file and proceed. It also gives the detailed procedure :

  • when sourceFile is a regular file
  • and when destinationFile exists
  • if a file descriptor for destinationFile can be obtained via actions such as open() (i.e. if destinationFile is writable by the current user)
    • THEN copy sourceFile into destinationFile
    • OTHERWISE delete destinationFile (if enough privileges to do so), then copy sourceFile as destinationFile

Check it :
touch file1; echo -e '\nRound 1'; cp file1 file2; echo -e '\nRound 2'; cp file1 file2; echo -e '\nRound 3'; chmod 200 file2; cp file1 file2; echo -e '\nRound 4a'; chmod 400 file2; cp file1 file2; echo -e '\nRound 4b'; cp -f file1 file2; echo -e '\nRound 5a'; chmod 000 file2; cp file1 file2; echo -e '\nRound 5b'; cp -f file1 file2; rm file[12]
Round 1		file2 didn't exist already, so that was easy !

Round 2		Piece of cake !!!

Round 3		w bit is set, no need to force

Round 4a
cp: cannot create regular file 'file2': Permission denied

Round 4b	w bit is NOT set, -f required

Round 5a
cp: cannot create regular file 'file2': Permission denied

Round 5b	no permission bit is set, -f required

Now if I try with file2 being a file I don't own, and on which I only have read permission (r--) :

cp file1 file2; cp -f file1 file2
cp: cannot create regular file 'file2': Permission denied
cp: cannot remove 'file2': Operation not permitted

As a conclusion, the -f / --force cp flag only serves to overwrite my own files if I have denied myself write access on them.

overwrite existing files or not

echo 'round 1' > file1; cp file1 file2; cat file2
round 1							normal copy (nothing to overwrite since file2 didn't exist yet)

echo 'round 2' > file1; cp file1 file2; cat file2
round 2							file2 silently overwritten

echo 'round 3' > file1; cp --update=none file1 file2; cat file2
round 2							file2 not overwritten thanks to explicit --update=none
			

More about --backup and suffix :

Make a backup of an existing destination :
touch myFile; cp myFile myFile_COPY; cp -b myFile myFile_COPY; ls -1; rm myFile*
myFile
myFile_COPY
myFile_COPY~
The default options do not overwrite the backup :
echo initial > myFile; cp myFile myFile_COPY; cp -b myFile myFile_COPY; echo modified > myFile; cp -b myFile myFile_COPY; ls -1; cat myFile myFile_COPY myFile_COPY~; rm myFile*
myFile
myFile_COPY
myFile_COPY~
modified
modified
initial		contents of myFile_COPY~
Make numbered backups :
echo 'initial version' > myFile; cp --backup=numbered myFile myFile_COPY; for i in {1..5}; do echo "edit $i" > myFile; cp --backup=numbered myFile myFile_COPY; done; for i in myFile*; do echo -en "$i :|"; cat "$i"; done | column -s '|' -t; rm myFile*
myFile :           edit 5
myFile_COPY :      edit 5
myFile_COPY.~1~ :  initial version
myFile_COPY.~2~ :  edit 1
myFile_COPY.~3~ :  edit 2
myFile_COPY.~4~ :  edit 3
myFile_COPY.~5~ :  edit 4
Make suffixed backups :
touch myFile; cp myFile myFile_COPY; cp -b --suffix='_OLD' myFile myFile_COPY; ls -1; rm myFile*
myFile
myFile_COPY
myFile_COPY_OLD
mail

continue

Usage

continue n

Example

Basic example : interrupting a single for loop :

#!/usr/bin/env bash

for i in {1..2}; do
	echo $i
	continue
	echo 'this will never be executed'
done
displays :
1
2

2 nested for loops :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		continue
		echo 'this will never be executed'
	done
done
displays :
1a
1b
2a
2b

2 nested for loops and continue 2 :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		continue 2
		echo 'this will never be executed'
	done
done
displays :
1a
2a
mail

column

Usage

Display data as columns

Flags

Flag Usage
-c n Use up to n characters-wide screen space to display data (get a terminal window's width and height)
-s char -t Consider char as the column separator in the input, then display data as columns
-t Determine the number of columns the input contains and create a table. Columns are delimited with whitespace, by default, or with the characters supplied with -s.

Example

for i in {1..3}; do echo col1_$i col2_$i; done | column -c 40
col1_1 col2_1	col1_3 col2_3
col1_2 col2_2
for i in {1..3}; do echo col1_$i col2_$i; done | column -t
col1_1	col2_1
col1_2	col2_2
col1_3	col2_3
for i in {1..3}; do echo col1_$i col2_$i; done | column -s 'l' -t
co	1_1 co	2_1
co	1_2 co	2_2
co	1_3 co	2_3
mail

chown

Flags

Flag Usage
-h --no-dereference Affect symlink instead of changing owner/group of its target
-R --recursive operate on files and directories recursively
--reference=referenceFile change owner + group like those of referenceFile (see also chmod's --reference)

Example

Command New user owner New group owner
chown bob myFile bob (unchanged)
chown bob:developers myFile bob developers
chown bob: myFile bob bob's login group
chown :developers myFile (unchanged) developers (equivalent to chgrp)
mail

chkconfig

Usage

chkconfig has been obsoleted by systemd and systemctl.

Flags

Flag Usage
--add serviceName add a new service for management
--del serviceName Unregister serviceName from chkconfig service management
--list
--list serviceName
List all the registered daemons and their runlevel activation status
List the runlevel activation status for serviceName only.
-s daemon on|off [level]
--set
Set the specified daemon ON or OFF for the specified runlevel. If no level is specified, the on/off is applied to ALL runlevels (?).
ex : chkconfig -s smb on

Example

List daemons with ON/OFF status for each runlevel :

  • chkconfig --list
  • chkconfig --list httpd

Enable / disable daemon on given runlevels :

These commands enable / disable daemons, but they don't start / stop them.

  • chkconfig --level 345 nscd off
  • chkconfig --level 3 httpd on

If no runlevel is specified, then all the possible runlevels are impacted :

chkconfig iptables off
(nothing)
chkconfig --list iptables
iptables	0:off	1:off	2:off	3:off	4:off	5:off	6:off
chkconfig iptables on
(nothing)
chkconfig --list iptables
iptables	0:off	1:off	2:on	3:on	4:on	5:on	6:off

Query a daemon activation status :

chkconfig iptables returns a Unix success / failure if iptables is enabled / disabled in the current runlevel :
chkconfig iptables off; chkconfig iptables; echo $?; chkconfig iptables on; chkconfig iptables; echo $?
1
0

When chkconfig complains error reading info for serviceName :

This happens :
  • when listing services : chkconfig --list 2>&1 | less
  • when taking actions on serviceName : chkconfig --del serviceName

In my case, this was caused by a broken link :

/etc/init.d/serviceName -> /installDir/serviceName/bin/scripts/serviceName.sh
Solution : fix this symlink (delete it if applicable, change target when possible)

How to specify runlevels and start/stop priority from within /etc/init.d/scriptName :

  1. add 2 commented lines in the header of scriptName :
    # chkconfig: runlevels startPriority stopPriority
    # description: description
    • runlevels : list of runlevels on which this script should start by default. To mean "none", just indicate -.
    • startPriority : (explicit)
    • stopPriority : (explicit)
    • description : (explicit) This can span on multiple lines with a trailing \ on each continued line.
  2. copy the script as /etc/init.d/scriptName
  3. register this new script : chkconfig --add scriptName
    This will create the appropriate symlinks :
    • /etc/rc.d/rcrunlevel.d/KstopPriorityscriptName -> ../init.d/scriptName
    • /etc/rc.d/rcrunlevel.d/SstartPriorityscriptName -> ../init.d/scriptName
mail

chattr

Usage

change file attributes. These attributes can be :

Flags

Flag Usage
-d target is a directory, not a regular file.

Example

Don't forget that the i flag requires privileges.
Set a file immutable :
chattr +i myFile
Remove the immutable flag from a file :
chattr -i myFile
Set a directory immutable :
chattr -d +i myDirectory
Remove the immutable flag from a directory :
chattr -d -i myDirectory
mail

cut

Usage

cut [options] file

Read file (or stdin if file is "-") line by line and display only the selected bytes, characters or fields.

Flags

Flag Usage
-b n display the nth byte
specify numeric arguments
-c n display the nth character
  • even though the manual is about characters, this flag actually selects bytes (1 character = 1 byte for ASCII strings only) :
    for myString in 'aeiouy' 'àèìòùy'; do echo "$myString" | cut -c 2-5; done
    eiou
    �è�	this is the 2nd byte of the à, then the è, then the 1st byte of the ì
  • specify numeric arguments, examples
-d character use character as field delimiter, defaults to TAB
-f n display the nth field
specify numeric arguments
--output-delimiter=string use string as the output delimiter. Defaults to the input delimiter, i.e. the value of -d

Numeric arguments for -b, -c and -f :

These apply to byte, character or field, depending on which flag is used.
  • n : nth, counted from 1
  • n- : from nth to end of line
  • n-m : from nth to mth (included)
  • -m : from first to mth (included)
  • x,y,z : the xth, the yth and the zth
    the data fields will be displayed following the order they have in the input, not the order you list them

Example

Basic examples

echo 'aze rty uio' | cut -d ' ' -f 2,3
rty uio
echo a,b,c | cut -d ',' -f2,3
b,c
echo a,b,c | cut -d ',' -f2,3 --output-delimiter=' '
b c
for i in {1..26}; do echo {a..z} | cut -d ' ' -f 1-$i; done
a
a b
a b c

a b c d e f g h i j k l m n o p q r s t u v w x y z

Select characters :

echo hello | cut -c 2
e
echo hello | cut -c -2
he
echo hello | cut -c 2-
llo