You can use GLOBIGNORE
to set the names that will be ignored while globbing and then use *
to match all other files/directories:
GLOBIGNORE='a:b:x'; rm -r *
Example:
$ tree
.
├── a
│ ├── 1
│ ├── 2
│ └── 3
├── b
│ ├── 1
│ ├── 2
│ └── 3
├── c
│ ├── 1
│ ├── 2
│ └── 3
├── x
├── y
└── z
/NASA$ GLOBIGNORE='a:b:x'
/NASA$ rm -r *
/NASA$ tree
.
├── a
│ ├── 1
│ ├── 2
│ └── 3
├── b
│ ├── 1
│ ├── 2
│ └── 3
└── x
Alternately, you can use find
, from the NASA
directory:
find . -maxdepth 1 ! -name '.' ! -regex '.*/\(a\|b\|x\)$' -exec rm -r {} +
Example:
/NASA$ tree
.
├── a
│ ├── 1
│ ├── 2
│ └── 3
├── b
│ ├── 1
│ ├── 2
│ └── 3
├── c
│ ├── 1
│ ├── 2
│ └── 3
├── x
├── y
└── z
/NASA$ find . -maxdepth 1 ! -name '.' ! -regex '.*/\(a\|b\|x\)$' -exec rm -r {} +
/NASA$ tree
.
├── a
│ ├── 1
│ ├── 2
│ └── 3
├── b
│ ├── 1
│ ├── 2
│ └── 3
└── x
I think find
is the right choice:
find */ -name "result.txt" -exec bash -c 'printf "%s,%s\n" "${0%%/*}" "$(cat $0)"' {} \;
Example run
$ echo r1 >a/b/result.txt
$ echo r2 >c/result.txt
$ tree
.
├── a
│ └── b
│ └── result.txt
└── c
└── result.txt
$ find */ -name "result.txt" -exec bash -c 'printf "%s,%s\n" "${0%%/*}" "$(cat $0)"' {} \;
a,r1
c,r2
Explanations
This find
command searches every file in or under the current directory of the name result.txt
and exec
utes the printf
command in a bash
subshell. The printf
command prints the subdir's name, a comma and the file content followed by a \n
ewline. If you want to write this output to a file, just append e.g. >final.csv
to the command.
Even simpler
is the -printf
approach suggested by steeldriver:
$ find */ -name 'result.txt' -printf '%H,' -exec cat {} \;
a/,r1
c/,r2
This prints an additional slash in the first column which you can easily remove by piping the output through e.g. sed 's|/,|,|'
.
Merging multiline result.txt
content into one cell
To replace newline characters with e.g. spaces just replace cat
with sed ":a;N;\$!ba;s/\n/ /g"
in one of the above commands, e.g.
$ find */ -name "result.txt" -exec bash -c 'printf "%s,%s\n" "${0%%/*}" "$(sed ":a;N;\$!ba;s/\n/ /g" $0)"' {} \;
a,r1 r1
c,r2
If you want some other string as the delimiter replace the / /
part with /your_delimiter/
, but keep the slashes.
Best Answer
A portable way (which will work on any POSIX compliant system):
In bash4, you can use globstar to get recursive globs (**):
The (perl)
rename
command in Ubuntu can rename files using perl regular expression syntax, which you can combine with globstar orfind
:Also see http://mywiki.wooledge.org/BashFAQ/030