3

I have the following folder and files:

.
├── photos
│   ├── photo-a
│   │   ├── photo-a.meta.json
│   │   └── photo-a.json
│   ├── photo-b
│   │   ├── photo-b.meta.json
│   │   └── photo-b.json
...
There are more folders and files in the photos folder in the same structure

I would want to copy all the files photo-a.json, photo-b.json and others into another folder called photos-copy. Basically, I want to exclude all the files that end with .meta.json but copy only those that end with .json files.

So, if done correctly, photos-copy folder would look like this:

.
├── photos-copy
│   ├── photo-a.json
│   └── photo-b.json
...

I tried something along cp -a ./photos/*.json ./photos-copy but this will end up copying everything because the .meta.json files also end with .json extensions.

How can I do this?

0

2 Answers 2

11

A couple of options spring to mind.

rsync --dry-run -av --prune-empty-dirs --exclude '*.meta.json' --include '*.json' photos/ photos-copy/

Or if you don't have rsync (and why not!?), this will copy the files retaining the structure

cp -av photos/ photos-copy/
rm -f photos-copy/*/*.meta.json

This variant will flatten the files into a single directory

cp -av photos/*/*.json photos-copy/
rm -f photos-copy/*.meta.json

You can do more fancy things with bash and its extended pattern matching, which here tells the shell to match everything that does not contain .meta in its name:

shopt -s extglob
cp -av photos/*/!(*.meta).json photos-copy/
6
  • Thanks a lot for the cp option! Just one thing, I notice that the files are still copied with their same folder in photos-copy. So, instead of copying to photos-copy/photo-a.json, they are still copied as photos-copy/photo-a/photo-a.json. Is there a way to copy and flatten it by one level to photos-copy/photo-a.json?
    – xenon
    Feb 23, 2022 at 17:15
  • @xenon try the extra alternatives I've added Feb 23, 2022 at 18:07
  • That's very cool! I tried the example you had with pattern matching, which I thought is cool, but I'm getting a syntax error: sh: -c: line 0: syntax error near unexpected token ('. Is there something I should take note of when using pattern matching? I have tried with and without the line shopt -s extglob` and I still got that syntax error.
    – xenon
    Feb 23, 2022 at 18:38
  • Sounds like you're using sh rather than bash. They're different shells Feb 23, 2022 at 20:46
  • 1
    The cp -av photos/*/!(*.meta).json photos-copy/ is very nice :). Thx.
    – K-attila-
    Feb 24, 2022 at 10:35
0

With rsync: rsync -rv --include="*/" --exclude="*.meta.json" --include "*.json" --exclude="*" ./photos/ photo-copy/

The original directory structure:

photo-a/photo-a.json
photo-a/photo-a.meta.json
photo-b/photo-b.json
photo-b/photo-b.meta.json
photo-b/photo-b.son

Output:

sending incremental file list
photo-a/photo-a.json
photo-b/photo-b.json

I tried it with the previous answer (rsync --dry-run -av --prune-empty-dirs --exclude '*.meta.json' --include '*.json' photos/ photos-copy/) output:

photo-a/photo-a.json
photo-b/
photo-b/photo-b.json
photo-b/photo-b.son

Explanation: In rsync include/exclude the order important. Include all subdirs 1st. Exclude the meta.json, include .json, and exclude any else.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .