Bash


How to execute `find` that ignores .git directories

Trying to find a source code file by its content using find and -exec grep, can some times result in getting results from the repository .git folders as well.

This behavior not only does it provide results you do not need but it also makes your search slower.
Below, we propose a couple of solutions on how to make a more efficient search.

Example 1: Ignore all .git folders no matter where they are in the search path

For find to ignore all .git folders, even if they appear on the first level of directories or any in-between until the last one, add -not -path '*/\.git*' to your command as in the example below.
This parameter will instruct find to filter out any file that has anywhere in its path the folder .git. This is very helpful in case a project has dependencies in other projects (repositories) that are part of the internal structure.


find . -type f -not -path '*/\.git/*';

Note, if you are using svn use:


find . -type f -not -path '*/\.svn/*';

Example 2: Ignore all hidden files and folders

To ignore all hidden files and folders from your find results add -not -path '*/\.*' to your command.


find . -not -path '*/\.*';

This parameter instructs find to ignore any file that has anywhere in its path the string /. which is any hidden file or folder in the search path!


How to get the pid of the last executed command that was sent to the background in a bash shell

Recently we came to the need of writing a bash script that needed periodically to check if a specific process, that was started by the script, had ended and restart it (something like watchdog but with not so many features).

To achieve this, we used the one of the shell special parameters, the $!. Like all other special parameters $! may only be referenced and the user cannot make an assignment to it.

($!) Expands to the process ID of the job most recently placed into the background, whether executed as an asynchronous command or using the bg builtin command.

From GNU.org: https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_0021-1

Example of Usage

In this example we wanted to get the PID of the application called server to be used later on in the script.


server &
echo $!; #This will print the process ID of the 'server' application


File permissions change date

Recently we wanted to check when did the permissions of a specific file changed.
Unfortunately, there exists no such flag and we do not have a 100% working solution for it.

What we did was to check the last modification time of the file status information (ctime) using the ls -lc command.
This command could indicate the last permissions change time but it is not a reliable source as it represents the modification time of other elements as well.

The modification time of the file status information (ctime) gets updated when any inode information regarding the file changes.
This means that the modification time of the file status information (ctime) will get updated when any of the following changes:

  • owner – The numeric user ID (UID) of the file’s owner.
  • group – The numeric group ID (GID) of the file’s group.
  • link count – The number of links to the file.
  • mode – The bit string that indicated the permissions and privileges
  • serial – The serial number of the file.
  • device – The numeric ID of the device containing the file.

Explanation of ls parameters

  • The parameter -c of the ls command when used with the -l will show ctime and sort by name.
  • The parameter -c of the ls command when used with the -l and the -t will show ctime and sort by ctime (newest first).

Example that demonstrates that we get different values in the time column of -l when -c is used

$ ls -lc ~/.ssh/
total 28
-rwx------. 1 george george  225 May 16 17:05 config
-rwx------. 1 george george 1743 Jun  2 13:36 id_rsa
-rwxrwx---. 1 george george  405 May 16 17:05 id_rsa.pub
-rwxrwx---. 1 george george   32 May 16 17:05 Details.txt
-rw-r--r--. 1 george george 9155 May 30 14:32 known_hosts

$ ls -l ~/.ssh/
total 28
-rwx------. 1 george george  225 Mar 22 11:36 config
-rwx------. 1 george george 1743 Jan 25 10:22 id_rsa
-rwxrwx---. 1 george george  405 Jan 25 10:22 id_rsa.pub
-rwxrwx---. 1 george george   32 Jan 25 10:22 Details.txt
-rw-r--r--. 1 george george 9155 May 30 14:32 known_hosts

Create a .tar file with different compression methods

The following commands will create .tar archives  and compress them using the different methods that are available. We provide multiple solutions, each one for a different type of .tar archive depending on the compression method that is desired.

For .tar archives

tar -c -f archive.tar $FILES_TO_ARCHIVE;

For .tar.bz2 archives

tar -c -j -f archive.tar.bz2 $FILES_TO_ARCHIVE;

For .tar.xz archives

tar -c -J -f archive.tar.xz $FILES_TO_ARCHIVE;

For .tar.gz and .tgz archives

tar -c -z -f archive.tar.gz $FILES_TO_ARCHIVE;

tar Parameters Legend

  • -z or --gzip instructs tar to filter the archive through gzip
  • -j or --bzip2 filters the archive through bzip2
  • -J or --xz filters the archive through xz
  • -f or --file=OUTPUT uses the archive file OUTPUT
  • -c or --create a new archive

Bonus Example: Create a tar.xz archive using the current date in the archive name

The following command will create an archive out of the folders Folder1 and Folder2 and then it will compress it to the .tar.xz format.
The filename of the archive will contain the current date in the format YYYY-MM-DD.

tar -c -J  -f archive.`date +%F`.tar.xz Folder1 Folder2;

The above command will result in something similar to:

archive.2017-06-04.tar.xz