Replicate directory structure applying a command to each file instead of simply copying it?
Clash Royale CLAN TAG#URR8PPP
Over time, I've encountered the same pattern again and again: I have some kind of directory structure:
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
And I want to "copy" the files over to another directory, say, example_grepped
, applying a command to each as if in place of cp
- say, grep ERROR
so that say, I end up with a folder with the same structure but with files filtered through the grep
.
example_grepped/
├── a
│ └── c
│ ├── d.txt (1k)
│ └── e.txt (0b)
└── b
└── f.txt (12k)
Same pattern for converting media files (FLACs to MP3s, PNGs to JPGs), and this time when converting different schema formats as part of a build process.
Is there a generic command that I could use? Something like foobar example example_grepped --command 'grep ERROR'
or foobar flacs mp3s --command 'ffmpeg -i .mp3'
?
An obscure xargs
flag perhaps? (a find
piped through xargs
would almost suffice, but most if not all commands expect the directory structure to already exist.)
xargs conversion filter
add a comment |
Over time, I've encountered the same pattern again and again: I have some kind of directory structure:
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
And I want to "copy" the files over to another directory, say, example_grepped
, applying a command to each as if in place of cp
- say, grep ERROR
so that say, I end up with a folder with the same structure but with files filtered through the grep
.
example_grepped/
├── a
│ └── c
│ ├── d.txt (1k)
│ └── e.txt (0b)
└── b
└── f.txt (12k)
Same pattern for converting media files (FLACs to MP3s, PNGs to JPGs), and this time when converting different schema formats as part of a build process.
Is there a generic command that I could use? Something like foobar example example_grepped --command 'grep ERROR'
or foobar flacs mp3s --command 'ffmpeg -i .mp3'
?
An obscure xargs
flag perhaps? (a find
piped through xargs
would almost suffice, but most if not all commands expect the directory structure to already exist.)
xargs conversion filter
To duplicate the directory structure you could usefind
withcpio
.cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit-v
if you don't want the directories to be listed while processing.) After this you can usefind
withxargs
as proposed in the question.
– Bodo
Jan 23 at 12:39
add a comment |
Over time, I've encountered the same pattern again and again: I have some kind of directory structure:
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
And I want to "copy" the files over to another directory, say, example_grepped
, applying a command to each as if in place of cp
- say, grep ERROR
so that say, I end up with a folder with the same structure but with files filtered through the grep
.
example_grepped/
├── a
│ └── c
│ ├── d.txt (1k)
│ └── e.txt (0b)
└── b
└── f.txt (12k)
Same pattern for converting media files (FLACs to MP3s, PNGs to JPGs), and this time when converting different schema formats as part of a build process.
Is there a generic command that I could use? Something like foobar example example_grepped --command 'grep ERROR'
or foobar flacs mp3s --command 'ffmpeg -i .mp3'
?
An obscure xargs
flag perhaps? (a find
piped through xargs
would almost suffice, but most if not all commands expect the directory structure to already exist.)
xargs conversion filter
Over time, I've encountered the same pattern again and again: I have some kind of directory structure:
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
And I want to "copy" the files over to another directory, say, example_grepped
, applying a command to each as if in place of cp
- say, grep ERROR
so that say, I end up with a folder with the same structure but with files filtered through the grep
.
example_grepped/
├── a
│ └── c
│ ├── d.txt (1k)
│ └── e.txt (0b)
└── b
└── f.txt (12k)
Same pattern for converting media files (FLACs to MP3s, PNGs to JPGs), and this time when converting different schema formats as part of a build process.
Is there a generic command that I could use? Something like foobar example example_grepped --command 'grep ERROR'
or foobar flacs mp3s --command 'ffmpeg -i .mp3'
?
An obscure xargs
flag perhaps? (a find
piped through xargs
would almost suffice, but most if not all commands expect the directory structure to already exist.)
xargs conversion filter
xargs conversion filter
edited Jan 23 at 12:35
Tomáš M.
asked Jan 23 at 12:29
Tomáš M.Tomáš M.
1614
1614
To duplicate the directory structure you could usefind
withcpio
.cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit-v
if you don't want the directories to be listed while processing.) After this you can usefind
withxargs
as proposed in the question.
– Bodo
Jan 23 at 12:39
add a comment |
To duplicate the directory structure you could usefind
withcpio
.cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit-v
if you don't want the directories to be listed while processing.) After this you can usefind
withxargs
as proposed in the question.
– Bodo
Jan 23 at 12:39
To duplicate the directory structure you could use
find
with cpio
. cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit -v
if you don't want the directories to be listed while processing.) After this you can use find
with xargs
as proposed in the question.– Bodo
Jan 23 at 12:39
To duplicate the directory structure you could use
find
with cpio
. cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit -v
if you don't want the directories to be listed while processing.) After this you can use find
with xargs
as proposed in the question.– Bodo
Jan 23 at 12:39
add a comment |
4 Answers
4
active
oldest
votes
Closest answer I can find without separately recreating the directory structure is to use install:
cd example
find . -type f -exec sh -c 'grep ERROR | install -D /dev/stdin /tmp/example_grepped/' ;
Unfortunately the above can only work if your command can throw its result to STDOUT.
add a comment |
Another way to approach this is to use a program that does recursive copies anyway. I checked rsync
, but could not find a callback option on a quick glance. But gnu tar
has an option --to-command
for which you can provide a command to be run that gets the file's input into stdin
. But how to get the file created then? Well, the command called finds the current file name in $TAR_FILENAME
.
Putting it all together, the basic call is
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
where script could be something like
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
Another way to approach this, would be to wrap the tar pipe in a script that gets the command to run on the command line. Yet the escaping for the mkdir ...dirname
construct will be a bit challenging.
add a comment |
#!/bin/bash
filter()
local target_root="$@: -1"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
This script also works with directory and file names that contain spaces.
Run this script where the source directory ("example") is located.
add a comment |
Using GNU Parallel you can do something like this:
cd src
find . -type f | parallel 'mkdir -p ../dst///; dostuff --input --output ../dst/'
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f496202%2freplicate-directory-structure-applying-a-command-to-each-file-instead-of-simply%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Closest answer I can find without separately recreating the directory structure is to use install:
cd example
find . -type f -exec sh -c 'grep ERROR | install -D /dev/stdin /tmp/example_grepped/' ;
Unfortunately the above can only work if your command can throw its result to STDOUT.
add a comment |
Closest answer I can find without separately recreating the directory structure is to use install:
cd example
find . -type f -exec sh -c 'grep ERROR | install -D /dev/stdin /tmp/example_grepped/' ;
Unfortunately the above can only work if your command can throw its result to STDOUT.
add a comment |
Closest answer I can find without separately recreating the directory structure is to use install:
cd example
find . -type f -exec sh -c 'grep ERROR | install -D /dev/stdin /tmp/example_grepped/' ;
Unfortunately the above can only work if your command can throw its result to STDOUT.
Closest answer I can find without separately recreating the directory structure is to use install:
cd example
find . -type f -exec sh -c 'grep ERROR | install -D /dev/stdin /tmp/example_grepped/' ;
Unfortunately the above can only work if your command can throw its result to STDOUT.
answered Jan 23 at 14:04
GohuGohu
8681317
8681317
add a comment |
add a comment |
Another way to approach this is to use a program that does recursive copies anyway. I checked rsync
, but could not find a callback option on a quick glance. But gnu tar
has an option --to-command
for which you can provide a command to be run that gets the file's input into stdin
. But how to get the file created then? Well, the command called finds the current file name in $TAR_FILENAME
.
Putting it all together, the basic call is
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
where script could be something like
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
Another way to approach this, would be to wrap the tar pipe in a script that gets the command to run on the command line. Yet the escaping for the mkdir ...dirname
construct will be a bit challenging.
add a comment |
Another way to approach this is to use a program that does recursive copies anyway. I checked rsync
, but could not find a callback option on a quick glance. But gnu tar
has an option --to-command
for which you can provide a command to be run that gets the file's input into stdin
. But how to get the file created then? Well, the command called finds the current file name in $TAR_FILENAME
.
Putting it all together, the basic call is
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
where script could be something like
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
Another way to approach this, would be to wrap the tar pipe in a script that gets the command to run on the command line. Yet the escaping for the mkdir ...dirname
construct will be a bit challenging.
add a comment |
Another way to approach this is to use a program that does recursive copies anyway. I checked rsync
, but could not find a callback option on a quick glance. But gnu tar
has an option --to-command
for which you can provide a command to be run that gets the file's input into stdin
. But how to get the file created then? Well, the command called finds the current file name in $TAR_FILENAME
.
Putting it all together, the basic call is
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
where script could be something like
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
Another way to approach this, would be to wrap the tar pipe in a script that gets the command to run on the command line. Yet the escaping for the mkdir ...dirname
construct will be a bit challenging.
Another way to approach this is to use a program that does recursive copies anyway. I checked rsync
, but could not find a callback option on a quick glance. But gnu tar
has an option --to-command
for which you can provide a command to be run that gets the file's input into stdin
. But how to get the file created then? Well, the command called finds the current file name in $TAR_FILENAME
.
Putting it all together, the basic call is
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
where script could be something like
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
Another way to approach this, would be to wrap the tar pipe in a script that gets the command to run on the command line. Yet the escaping for the mkdir ...dirname
construct will be a bit challenging.
answered Jan 23 at 21:14
HaraldHarald
325112
325112
add a comment |
add a comment |
#!/bin/bash
filter()
local target_root="$@: -1"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
This script also works with directory and file names that contain spaces.
Run this script where the source directory ("example") is located.
add a comment |
#!/bin/bash
filter()
local target_root="$@: -1"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
This script also works with directory and file names that contain spaces.
Run this script where the source directory ("example") is located.
add a comment |
#!/bin/bash
filter()
local target_root="$@: -1"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
This script also works with directory and file names that contain spaces.
Run this script where the source directory ("example") is located.
#!/bin/bash
filter()
local target_root="$@: -1"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
This script also works with directory and file names that contain spaces.
Run this script where the source directory ("example") is located.
edited Jan 24 at 1:02
answered Jan 23 at 19:04
Niko GambtNiko Gambt
1836
1836
add a comment |
add a comment |
Using GNU Parallel you can do something like this:
cd src
find . -type f | parallel 'mkdir -p ../dst///; dostuff --input --output ../dst/'
add a comment |
Using GNU Parallel you can do something like this:
cd src
find . -type f | parallel 'mkdir -p ../dst///; dostuff --input --output ../dst/'
add a comment |
Using GNU Parallel you can do something like this:
cd src
find . -type f | parallel 'mkdir -p ../dst///; dostuff --input --output ../dst/'
Using GNU Parallel you can do something like this:
cd src
find . -type f | parallel 'mkdir -p ../dst///; dostuff --input --output ../dst/'
answered Jan 30 at 19:06
Ole TangeOle Tange
12.4k1454105
12.4k1454105
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f496202%2freplicate-directory-structure-applying-a-command-to-each-file-instead-of-simply%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
To duplicate the directory structure you could use
find
withcpio
.cd /path/to/example && find . -type d|cpio -pdv /path/to/example_grepped
. (Omit-v
if you don't want the directories to be listed while processing.) After this you can usefind
withxargs
as proposed in the question.– Bodo
Jan 23 at 12:39