Ubuntu – Write the dynamic output of terminal into a text file

bashcommand linescriptssoundsox

It comes down to being able to save the dynamic output (I'll explain) of terminal into a text file, but here's what I'm ultimately seeking.

I created a custom command for terminal called playRandom, what it does is that it plays random songs forever. The bash file I created for this:

find ./ -type f | sort -R | xargs -I + play +

Note: The play command is from SoX software.

Now the output looks something like this:

playRandom command

As you can see the output changes dynamically, so I cannot use >> to save the output.

I want to be able to save 'names of songs that are played' into a text file.

How can I achieve this goal? Thanks in advance.

Best Answer

Saving filenames that are played currently

Since the play command terminates after playing a single file, what we can do is instead of using xargs and giving play a batch of files, we'll take out each file, one at a time, and echo it to file, and play the file afterwards. The edited script would look like below. Notice that here are added additional options and IFS= read -d'' -r command to deal with filenames in safe manner.


# create file for playing songs first
echo > playlist.txt

# Now play each song and echo filename to file
find ./ -type f -print0 | sort -z -R | while IFS= read -d '' -r filename
    echo "$filename" >> playlist.txt
    play "$filename"

The advantage of this approach is that filenames will go into playlist.txt as they are played, which allows us to track output of the script in real time with something like tail -F playlist.txt.

NOTE: to avoid playlist.txt being listed in find's output change find command like so:

find ./ -type f -not -name "playlist.txt" -print0

Additionally if we want to ensure that only .mp3 files are listed we can do this:

find ./ -type f \( -not -name "playlist.txt" -and -name "*.mp3" \) -print0

Saving list of found files to be played

If our goal is to safe the file list before it is played, there's not a lot of science to it - the find-sort pipeline can be written to file first, and that file can then be fed to play either via xargs or again via while IFS= read -r ; do ... done structure


find ./ -type f -print0 | sort -z -R > playlist.txt

while IFS= read -d '' -r filename
    play "$filename"
done < playlist.txt
Related Question