I normally watch many logs in a directory doing tail -f directory/*. The problem is that a new log is created after that, it will not show in the screen (because * was expanded already).

Is there a way to monitor every file in a directory, even those that are created after the process has started?

8 Answers 8


You can tail multiple files with… multitail.

multitail -Q 1 'directory/*'

-Q 1 PATTERN means to check for new content in existing or new files matching PATTERN every 1 second. Lines from all files are shown in the same window, use -q instead of -Q to have separate windows.

  • I know this question was asked earlier in 2015 but I am running today in same issue. I have multiple dir and sub-dir and using this PATTERN ''logs/**/*' but though this watches for new files in a directory but does not work in terms of recursion. It looks for only in Grandchild directory of logs.
    – Nish
    Jun 13, 2020 at 20:01
  • @Nish Indeed I don't think multitail implements any form of directory recursion. Jun 14, 2020 at 11:31
  • This is great! It would be even more useful if I could use it more like tail-- without any of the ncurses control. I.e., so I could just scroll upwards like normally and see the prior contents. In my use case, I don't care which file the output is coming from. But I do want to easily scroll back upwards. I'm currently using a command multitail -d -Q 1 'directory/*' but don't get any scrolling upwards. Jul 25, 2020 at 23:47
  • 2
    looks like this is no longer maintained Aug 25, 2021 at 15:53

xtail is also an alternative. Its man page describes it as:

Xtail monitors one or more files, and displays all data written to a file since command invocation. It is very useful for monitoring multiple logfiles simultaneously. If an entry given on the command line is a directory, all files in that directory will be monitored, including those created after the xtail invocation. If an entry given on the command line doesn’t exist, xtail will watch for it and monitor it once created. When switching files in the display, a banner showing the pathname of the file is printed.

An interrupt character (usually CTRL/C or DEL) will display a list of the most recently modified files being watched. Send a quit signal (usually CTRL/backslash) to stop xtail.


Also you can watch directory with watch

watch -n0,1 "ls -lrt /directory/ | tail"
  • Minor nitpick: watch redraws the screen in the alternative buffer, with the first x lines of output from the command. Across a number of files with no changes, if the earlier files do not change, the tail might render the same thing each time, so you get the appearance of no additional entries, as they are drawn in later files 'below' the bottom of the screen. For a short file, though, this is fine... Aug 7, 2017 at 20:08
  • 3
    This does not give a solution to the original problem. This just outputs (the last few lines of) a directory listing (repeatedly, always current - thanks to watch), instead of the latest lines of all files (including new ones) in that directory.
    – trs
    Oct 2, 2018 at 19:43
  • It took me a few tries to realize that "watch -n0,1" was either a typo or done in a different I18N context, and that "watch -n0.1" works in EN_US.
    – Codex24
    Mar 16, 2023 at 22:33

No idea about a shell solution, but (assuming Linux1) inotify could be the way to go... see this example imitating tail -F (using pyinotify), maybe it can be used as a basis for following an entire directory.

In general, inotify can monitor directories (citing man 7 inotify)

The following bits can be specified in mask when calling inotify_add_watch(2) and may be returned in the mask field returned by read(2):

IN_ACCESS         File was accessed (read) (*).
IN_ATTRIB         Metadata changed, e.g., permissions, timestamps,
                    extended attributes, link count (since Linux 2.6.25),
                    UID, GID, etc. (*).
IN_CLOSE_WRITE    File opened for writing was closed (*).
IN_CLOSE_NOWRITE  File not opened for writing was closed (*).
IN_CREATE         File/directory created in watched directory (*).
IN_DELETE         File/directory deleted from watched directory (*).
IN_DELETE_SELF    Watched file/directory was itself deleted.
IN_MODIFY         File was modified (*).
IN_MOVE_SELF      Watched file/directory was itself moved.
IN_MOVED_FROM     File moved out of watched directory (*).
IN_MOVED_TO       File moved into watched directory (*).
IN_OPEN           File was opened (*).

When monitoring a directory, the events marked with an asterisk (*) above can occur for files in the directory, in which case the name field in the returned inotify_event structure identifies the name of the file within the directory.

(...and pyinotify closely follows theses options)

1: BSDs have a similar thing, kqueue. Maybe a cross-platform solution is achievable using GIO (Python bindings) as abstraction layer since it can, beside inotify, also use kqueue


I wrote a quick one that fulfils the need.

BASE_DIR=$(dirname $LOG_PATTERN* | head -1)

run_thread (){
    echo Running thread
    tail -F $LOG_PATTERN* &

# When someone decides to stop the script - killall children
cleanup () {
    pgrep -P $$ | xargs -i kill {}


if [ $# -ne 1 ]; then
    echo "usage: $0 <directory/pattern without * in the end>"
    exit 1

# Wait for the directory to be created
if [ ! -d $BASE_DIR ] ; then
    echo DIR $BASE_DIR does not exist, waiting for it...
    while [ ! -d $BASE_DIR ] ; do
        sleep 2
    echo DIR $BASE_DIR is now online

# count current number of files
OLD_NUM_OF_FILES=$(ls -l $LOG_PATTERN* 2>/dev/null | wc -l)

# Start Tailing

while [ 1 ]; do
    # If files are added - retail
    NUM_FILES=$(ls -l $LOG_PATTERN* 2>/dev/null | wc -l)
    if [ $NUM_FILES -ne $OLD_NUM_OF_FILES ]; then
        kill $THREAD_PID
    sleep 1
  • 1
    Actually, you can ommit the sleep 1 in the main loop, will be more snappy to get new files. But I don't like that kind of busy waits
    – Itamar
    Jun 24, 2015 at 10:19
  • 1
    Due to the sleep this is not a busy wait but soft on the CPU, just polling. One could change it to sleep 0.2s (GNU sleep) or whatever to make it faster if required.
    – Ned64
    Oct 4, 2019 at 16:37

This works recursively.

It makes use of inotify (apt-get install inotify-utils on Debian) and just restarts the tail commands whenever new files/directories are discovered.

while true; do
        ( find "$logDir" -type f -print0 | xargs -0 tail --verbose --follow --lines=0 )&
        inotifywait --recursive --quiet --event create --format=%w%f "$logDir" | tr \\n \\0 | xargs -0 tail --verbose
        kill $tailPid

My use case was redirecting all logs to /dev/stderr inside a docker container to have them show up in docker-compose logs -f.

  • This was the most useful answer for me. Inotify and the inotifywait command don't work on Sshfs paths, but then you can do ssh HOST inotifywait ...... Apr 8, 2021 at 3:16

Here's a bash script that also uses inotifywait. It watches for any new or changed file and runs tail --verbose -n {NN} on that file, which prints the filename and last NN lines.

function usage() {
  echo "Usage: $0 {folder} [#lines]
  Monitor {folder} and execute 'tail -n [#lines]'
  for any new or modified files.
  Default [#lines] is $NLINES.
  exit 1
[[ ! -z $1 ]] || usage
[[ -d $1 ]] || {
  echo "ERROR: $1 is not a a folder."
[[ -z $2 ]] || {
  [[ $2 =~ ^[0-9]+$ ]] && NLINES=$2 || {
    echo "ERROR: [#lines] must be an integer"
inotifywait -m -e modify -e create --format=%w%f $1 | xargs -d '\n' -n 1 tail --verbose -n $NLINES

Perhaps this is a little different, but I had a need to monitor a directory and show the end of the most recent file continuously, on a (way back-level) system to which I could make no admin changes. That eliminated availability of inotify, multitail, or any new binaries, so a one-liner script is desirable. To do this, I modified @zombic's approach to the following:

watch -n5 "ls -tr $PWD | tail -1 | xargs -l tail -n $(( $LINES -2 ))"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .