-3

I am having trouble trying to output all my .mp4 films into a text file, it works but there are a few quirky things occurring and I am not sure why.

Here is the cmd.

find "/volume1 HD FILMS" -iname "*.mp4" -type f -exec ls {} \; > "/volume1/3. HD FILMS/HD_FILMS_`date +%d.%m.%Y`.txt"
  1. why is it outputting the path? when an ls inside the directory just prints the file (which is what I want)
  2. why is the output file, not in alphabetical order (again compare to an ls inside the dir - it seems random)

How can I fix these issues?

Thomas Dickey
  • 76,765

1 Answers1

2

To answer your exact questions:

why is it outputting the path? when an ls inside the directory just prints the file (which is what I want)

It's outputting the path because you're not inside the directory. ls somedir is different from cd somedir; ls.

why is the output file, not in alphabetical order (again compare to an ls inside the dir - it seems random)

ls puts files in alphabetical order and then outputs them all. So it has an opportunity to sort them before printing them.

When you use find with -exec and terminate the command with \;, you are explicitly telling find to run one command (in this case one ls command) for every file found by find. Thus there is no possibility to sort them.

If you used ls -l you would also notice that the columns were not aligned correctly, since each printed line is actually output from a different command.

Instead, you could consider using find ... -ls or find ... -print, or if it's really necessary to use -exec ls, you could use -exec ls {} +, which should handle the sorting for the most part. (Specifically, it is likely to sort all files together, but if there is such a large number that it exceeds your system's ARG_MAX, then find will be forced to use separate ls commands and those separate batches will be sorted separately.)


Note: I personally would never save such a list of filenames into a text file, because filenames can contain newlines. There is no foolproof way to parse a text file into individual file names. Period. (See Why not parse ls?)

Instead, I would just run the find command when I wanted to do something with the files, not run it in advance and then try to do something with the earlier output.

If I wanted to generate a human readable list of all my mp4 files, I would emphasize that these can NOT be relied on as filenames by stripping out the path components:

find "/volume1 HD FILMS" -iname "*.mp4" -type f -print | sed 's:.*/::;s/\.[mM][pP]4$//' > "/volume1/3. HD FILMS/HD_FILMS_$(date +%d.%m.%Y).txt"
Wildcard
  • 36,499