Using yes command for commands or scripts that need interactive response
If some commands or scripts need user interaction and you know that you have to enter Y each time it requires input, you can use the Yes
command:
yes | command_or_script
Working with file and directories
Let's say we need to create those 4 directories:
- dir_images
- dir_pdf
- dir_zip
- dir_log
Of course one could 4x make use of the mkdir
command. Or you do it in just 1 line of code:
$> mkdir -v dir_{images,pdf,zip,log}
mkdir: created directory 'dir_images'
mkdir: created directory 'dir_pdf'
mkdir: created directory 'dir_zip'
mkdir: created directory 'dir_log'
Creating several nested directories at one
Let's say we want to create these directories
- /foo
- /foo/bar
- /foo/bar/zoo
- /foo/bar/zoo/whatever
We simply could do
$> mkdir foo && mkdir foo/bar && mkdir foo/bar/zoo && mkdir foo/bar/zoo/whatever
or we save us a lot of typing by adding the -p flag which creates missing parent directories as needed
$> mkdir -p foo/bar/zoo/whatever
Now we want to replace (=move) all *.txt
files to *.log
files, so we run a foor loop:
$> for f in ./*.txt; do mv -v ”$file” ”${file%.*}.log”; done
renamed './file10.txt' -> './file10.log'
renamed './file1.txt' -> './file1.log'
renamed './file2.txt' -> './file2.log'
renamed './file3.txt' -> './file3.log'
renamed './file4.txt' -> './file4.log'
But when you have the prename command available, you could do this more easily by:
$> prename -v 's/.txt/.log/' *.txt
file10.txt -> file10.log
file1.txt -> file1.log
file2.txt -> file2.log
file3.txt -> file3.log
file4.txt -> file4.log
Before modifying a configuration file, I is a good practice to make a backup copy of the original one by using a basic copy command like f.e.:
$> cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.back
But repeating the whole path and appending .back to the file isn't that sexy and probably error-prone. There is a shorter, neater way to do this:
$> cp /etc/sysconfig/network-scripts/ifcfg-eth0{,.back}
Check if a file is a symbolic link
$> [[ -L /path/to/file ]] && echo "passed file is a symlink"
Read a file line by line & do something with it's line content
First let us create a file with some names in is
$> cat << EOF >> names.txt
Jane Smith
John Doe
Alice Smith
Marc Brown
EOF
In this command:
<< EOF
: Starts ahere
document (also referred to as a "heredoc"). It's a way to pass multiline input to a command. Thehere
document starts with<<
followed by a delimiter. In our example,EOF
(End Of File) is used as the delimiter, but it's really just a convention; you could use any word or phrase as long as it's the same at the beginning and the end of thehere
document.>> names.txt
: Tells the shell to append the contents of thehere<c/ode> document to
names.txt
.- The lines between
<< EOF
and the secondEOF
are the contents of the here document. These lines will be appended tonames.txt
.
Print out the names in the created file via a WHILE loop:
$> while read -r line; do echo "$line"; done < names.txt
Print out the names in the file via a FOR loop:
for name in $(cat names.txt); do echo "$name"; done
But the FOR loop seperates lines by whitespace by default. So "Jane Smith" would be one line with "Jane" and another one with "Smith". We will have to set the Internal Field Separator (IFS) to "newline":
$> IFS=$'\n'; for name in $(cat names.txt); do echo "$name"; done
Identify Open Files
The lsof
command stands for List Open Files. It is easy to remember lsof
command if you think of it as “ls + of”, where ls stands for "list", and of stands for "open files".
Simply typing lsof
will provide a list of all open files belonging to all active processes:
$> lsof COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME init 1 root cwd DIR 8,1 4096 2 / init 1 root txt REG 8,1 124704 917562 /sbin/init init 1 root 0u CHR 1,3 0t0 4369 /dev/null init 1 root 1u CHR 1,3 0t0 4369 /dev/null init 1 root 2u CHR 1,3 0t0 4369 /dev/null init 1 root 3r FIFO 0,8 0t0 6323 pipe ...
List processes which opened a specific file:
$> lsof /var/log/syslog
List opened files based on process names starting with:
$> lsof -c ssh -c init
You can list the files opened by process names starting with a string, using -c option. -c followed by the process name will list the files opened by the process starting with that processes name. You can give multiple -c switch on a single command line.
List all processes using a certain mount point
Sometime when we try to umount a directory, the system will say “Device or Resource Busy” error. So we need to find out what are all the processes using the mount point and kill those processes to umount the directory. By using lsof
we can find those processes:
$> lsof /home
List all files opened by a specific user:
$> lsof -u username
When you want to list files opened by all users, expect some users you can use the ^
to exclude only the particular user as follows:
$> lsof -u ^username
List all open files by a specific process by passing the PID:
$> lsof -p 1753
Kill all processes that belong to a particular user:
$> kill -9 `lsof -t -u username`
Finding Network Connection
Network connections are (technically) also files. So we can find information about them by using lsof
by adding the -i option.
$> lsof -i
List all network files in use by a specific process
You can list all the network files which are being used by a process by passing the PID (process ID):
$> lsof -i -a -p 234
or even by passing the name of the process (here: ssh)
$> lsof -i -a -c ssh
List processes which are listening on a particular port:
$> lsof -i :25