Name of first file in directory obtained in optimal way
This is tricky. Two approaches:
Approach 1; find
:
find . -mindepth 1 -print -quit
find
and -print
s the first file found, and -quit
s immediately. -mindepth 1
would prevent matching the .
hardlink of the current directory.
If you are interested in regular files only, add -type f
:
find . -type f -print -quit
-mindepth 1
can be dropped then as the .
being a directory would not be matched.
Approach 2; sh
, stdbuf
, and awk
:
Note that, this might suffer from ARG_MAX
being triggered for too many files (argument list becoming too long, over ARG_MAX
bytes). In that case, use approach 1.
- any shell builin (e.g.
printf
,echo
) to print the filename - shell globbing,
*
, to do the expansion (the collation order should be the same asls
for a givenlocale
'sLC_COLLATE
) stdbuf -o0
(stdbuf
comes with GNUcoreutils
) to make the STDOUT stream ofprintf
/echo
unbuffered- pipe (
|
) the STDOUT ofprintf
/echo
toawk
andexit
after printing the first record - After
awk
exits,stdbuf
(printf
) would receiveSIGPIPE
, and would be killed - I would use
printf
to get the filenames separated by ASCII NUL (\0
), and use\0
as the record separator inawk
to tackle any edge cases as far as the filenames are concerned
Putting these together:
stdbuf -o0 printf '%s\0' * | awk 'BEGIN{RS="\0"} {print; exit}'
Related videos on Youtube
Daniel
I write blogs in English https://preciselab.io and Polish https://gustawdaniel.com
Updated on September 18, 2022Comments
-
Daniel over 1 year
Ordinary when I want to show name of first file from directory I type:
ls raw/all | head -n 1
But it takes long time when in directory there any many files
Eg for dir with near to 900 k files we have following measurements:
time ls raw/all | head -n 1 real 0m17.250s | 0m10.328s | 0m6.334s user 0m3.224s | 0m3.884s | 0m3.192s sys 0m0.544s | 0m0.664s | 0m0.572s
while loop over all files takes:
time ls raw/all | wc -l real 0m6.455s | 0m5.869s | 0m5.228s user 0m3.612s | 0m3.468s | 0m4.072s sys 0m0.460s | 0m0.784s | 0m0.624s
How print name of first file in efficient way?
-
Daniel over 6 yearsLooks awesome but: stdbuf -o0 printf '%s\0' raw/all/* | awk 'BEGIN{RS="\0"} {print; exit}' first froozen my terminal, but on catalog with 200k files prints:
bash: /usr/bin/stdbuf: List of arguments too long
. So if it is impossible to get first file due to sorting, we can change question: "How to get any filename, not necessary first?" -
heemayl over 6 years@Daniel Ahhh,
ARG_MAX
is being triggered. Doesfind . -mindepth 1 -print -quit
work? Prependstdbuf -o0
as well... -
Daniel over 6 yearsYes. Please update your answer and explain why We want to have
unbuffored
stream? It works with and without stdbuf -o0. -
heemayl over 6 years@Daniel Updated.
stdbuf -o0
is not needed here becausefind
is quitting immediately, no chance of storing in buffer and flushing later.