createdToday Command

createdToday Command

In the table on our linux commands page, the following bash command was used to illustrate a rather complicated alias command:

$ alias createdToday=' TODAY=` date | cut -c5-10 ` ; LIST=` \ls -lc | grep "${TODAY}" | cut -f2 -d: | cut -f2 -d" " `; for file in ${LIST} ; do echo ${file} ; done ; unset TODAY LIST '

This example is complicated and a careful description of what is happening here seems like a good way to explain why and how some of the concepts described in our brief linux tutorial can be strung together to accomplish something useful.

The command is a single long line of text that effectively creates a user-defined command called createdToday. This new command lists all files in the current area that were created or modified today. It does this by combining some standard commands that the bash shell understands and a mixture of command separator symbols (;), command substitution symbols (the pairs of `'s) and several pipes (the | symbols, which make the output of one command become input to the next).

If this command had been written for the tcsh shell, it would only appear marginally different.

It is much easier to see what this command is doing and how it works if it is broken down into more easily read "logical units" using colors

$ alias createdToday=' TODAY=` date | cut -c5-10 ` ; LIST=` \ls -lc | grep "${TODAY}" | cut -f2 -d: | cut -f2 -d" " `; for file in ${LIST} ; do echo ${file} ; done ; unset TODAY LIST '

or (better yet) using separate lines for the different units:

$ alias createdToday=' TODAY=` date | cut -c5-10 ` ;
LIST=` \ls -lc | grep "${TODAY}" | cut -f2 -d: | cut -f2 -d" " ` ;
for file in ${LIST} ;
do echo ${file} ;
done ;

NOTE: While you could cut and paste the single line command into a linux terminal window and create the correct command, if you try the same thing with this set of comnmands broken into separate lines, it will fail completely. You could, however, ignore the bits containing " alias createdToday=" and the semi-colons (the ;'s), and instead cut and paste each separate line into a terminal window. This sequence of commands would list the files created today, which is what the createdToday command is designed to do. The alias command simply combines all these steps into a new, user-created command.

As shown above, this command can be broken into four main segments:

  1. The first step creates a user-specific environmental variable called TODAY that simply contains the current month and day. This is done by executing the date command and piping (the | symbol) the output into a cut command that retains only the proper region of output characters ( the -c5-10 option to cut says "keep the 5th through 10th characters from the input"). This step could have been accomplished using several other commands, and this is simply one way to accomplish the goal.
  2. The next step creates another user-specfic environmental variable called LIST that contains the names of all the files and directories that were created today. This begins with a \ls -lc command, where the option -lc ensures that the long listing contains what is called the ctime for all files and directories (where ctime is the time of last modification for a file) and \ls ensures that you are not accidentally using some alias for ls that would cause the ls -lc command to generate something unexpected.

    The output of \ls -lc is piped into a grep command that only outputs those lines which contain the current month and day, which was stored by the first part of the command in TODAY.

    NOTE: Since the entire definition of the alias command is delimited using single quotes (the ' symbols surrounding everything after the = sign in the alias command), in order to promote the variable ${TODAY} to its actual value, it was necessary to enclose that variable name in double quotes (the " symbols).

    The output from grep is then piped into two cut commands. The first cut saves the second field of each line that is delimited by a colon: the option -f2 means 'field 2' and -d: means 'delimited by the symbol for colon (:)'. That output is then piped into a second cut that saves the second field of output from the first cut command that is delimited by spaces: the option -f2 again means 'field 2' and -d" " means 'delimited by a space (" ")'.

    NOTE: Since the grep command looks only for today's month and day, you might think that this command would be confused by files that have a ctime with the same month and day but a different year (or that the grep command should include the year). However, output from the ls -lc command shows the year only for files where the ctime denotes previous years. For files from the current year, ls -lc generates the month, day and the time-of-day (formatted as HH:MM). Since file names should not contain colons, the colon in HH:RR is the only one present in a line generated by ls -lc. By selecting the second field delimited by a colon, the cut command completely eliminates all files where the ctime denotes the previous year (i.e., the second field in a situation where the field delimiter does not exist is empty) and keeps the last part of any line that contains today's month and day, and a time-of-day designation.
  3. The third step is itself a complicated expression formed around the built-in bash command for. This expression is called a "for loop." The first and last (third) line start and stop the loop, while the middle can actually be composed of multiple lines. The net effect of the for loop is that every entry in the variable LIST is printed to the terminal. If you replace the middle line of this unit (do echo ${file} ;) with do ls -l ${file} ; instead, the output will be a long listing for each of the files or directories created or modified today.

    NOTE: If the alias for createdToday had been written for the tcsh shell, this "for loop" would need to be replaced using the built-in tcsh command foreach which performs the same sort of function but using a slightly different syntax.
  4. The fourth and final step simply cleans up after everything: unset name is a built-in bash command (and other shells will have identically named buit-in commands) that removes (eliminates) the variable called name. unset is used here to destroy the variables TODAY and LIST that were created at the beginning of the createdToday command. It is unlikely that forgetting to unset these two variables would actually cause any problems after the command was run, but it never hurts to clean up after yourself!