Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash "map" equivalent: run command on each file [duplicate]

Tags:

bash

shell

map

I often have a command that processes one file, and I want to run it on every file in a directory. Is there any built-in way to do this?

For example, say I have a program data which outputs an important number about a file:

./data foo
137
./data bar
42

I want to run it on every file in the directory in some manner like this:

map data `ls *`
ls * | map data

to yield output like this:

foo: 137
bar: 42
like image 470
Claudiu Avatar asked Apr 14 '10 19:04

Claudiu


People also ask

What does &> mean in bash?

&>word (and >&word redirects both stdout and stderr to the result of the expansion of word. In the cases above that is the file 1 . 2>&1 redirects stderr (fd 2) to the current value of stdout (fd 1).

How do I duplicate a file in bash?

Copy a File ( cp ) You can also copy a specific file to a new directory using the command cp followed by the name of the file you want to copy and the name of the directory to where you want to copy the file (e.g. cp filename directory-name ).

What is &2 in bash script?

and >&2 means send the output to STDERR, So it will print the message as an error on the console. You can understand more about shell redirecting from those references: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Redirections.


3 Answers

If you are just trying to execute your data program on a bunch of files, the easiest/least complicated way is to use -exec in find.

Say you wanted to execute data on all txt files in the current directory (and subdirectories). This is all you'd need:

find . -name "*.txt" -exec data {} \;

If you wanted to restrict it to the current directory, you could do this:

find . -maxdepth 1 -name "*.txt" -exec data {} \;

There are lots of options with find.

like image 145
Daniel Haley Avatar answered Oct 21 '22 19:10

Daniel Haley


If you just want to run a command on every file you can do this:

for i in *; do data "$i"; done

If you also wish to display the filename that it is currently working on then you could use this:

for i in *; do echo -n "$i: "; data "$i"; done
like image 33
Mark Byers Avatar answered Oct 21 '22 18:10

Mark Byers


It looks like you want xargs:

find . --maxdepth 1 | xargs -d'\n' data

To print each command first, it gets a little more complex:

find . --maxdepth 1 | xargs -d'\n' -I {} bash -c "echo {}; data {}"
like image 34
Stephen Avatar answered Oct 21 '22 19:10

Stephen