It is very simple to use Perl's glob for the filelist and then process files
perl -MPath::Tiny -we'path($_)->edit_lines( sub { s/hi/bye/ } ) for glob "files*"'
Here I use Path::Tiny with its edit_lines
(see edit
) while there are yet other tools for this.
A call to glob
in the list context† returns a list and we iterate over it, editing the file in a single statement. If there is more to do, or you'd rather open a file by hand and go through lines, then can put that code in a do
block
perl -wE'do { ...process file... } for glob "files*"'
It there are so many files that the shell has a problem with the list then you may want to avoid building it in Perl as well, which is what glob
does in list context. (Even as there is no limit, nor a disastrous performance impact.)
There's a number of ways to take those files one by one -- using File::Find, or things like readdir
in scalar context or Path::Tiny::iterator. This requires selection of entries they find by regex so a "translation" of the glob, but that shouldn't be a problem given how simple glob patterns are. Or use glob
in scalar context.†
If there may be spaces in entry names use File::Glob -- merely adding use File::Glob qw(:bsd_glob);
to the program will use that instead of glob
. With a one-liner one can do
perl -MFile::Glob=":bsd_glob" -wE'...'
In this case you can also suppress sorting that glob
does by using GLOB_NOSORT
flag, good to do for large filelists unless you need them sorted. Then we have to actually replace glob
perl -MFile::Glob=":bsd_glob" -wE'do { ... } for bsd_glob("files*", GLOB_NOSORT)'
Tools other than glob
, like ones mentioned above, don't care about spaces in names.
† Another way is to use glob
in the scalar context, when it acts as an iterator, and process each file as it is returned
perl -wE'do { ... } while "files*"'
(Or while (glob "files*") { ... }
)
This avoids building the potentially huge list upfront.
bash
problem, but an issue for operating systems that don't allow arbitrarily long command lines. – Putonprintf '%s\0' too_many_files* | xargs -0 perl -pi -e 's/hi/bye/'
, the perl command is quoted exactly the same way as your original code. – Decreeparallel -q
has sometimes been handy, and sometimes insufficient. – Bifurcateparallel
tries to be "smart" in ways that make quoting difficult. I strongly advise against its use. For background, the thread at lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html, and the Unix & Linux question unix.stackexchange.com/questions/349483/… are good places to start. xargs is much less clever, does fewer things behind your back, and generally leans towards making only easily-foreseeable kinds of trouble. – Decree