0

I have a variable with path to folder1 containing a white space:

TEST=path/with\ space/to/folder1/

I want to concatenate all files within a folder1 with cat but it gives an error:

cat "$TEST"* > test
cat: path/with: No such file or directory
cat: 'space/to/folder1/*': No such file or directory

When I try to do that directly cat path/with\ space/to/folder1/ > test it works.

Also, it works with double quotes:

TEST="path/with space/to/folder1/"
cat "$TEST" > total

But how to do it right via the \ in the path?

trilisser
  • 103

1 Answers1

0

I'd use find with its -exec option for this. For example:

TEST='path/with space/to/folder1/'
find "$TEST" -maxdepth 1 -type f -exec cat {} + > test

The -maxdepth 1 option prevents recursion into sub-directories below "$TEST". You can change or remove that as required. -type f matches only regular files (i.e. excludes directories, named pipes, symbolic links, etc).

If you want it to match specific filename patterns, you can use the -name or -regex options (e.g. -name '*.txt') or the case-insensitive -iname / -iregex.

find has a lot more options and is very flexible - but it's also very complex and takes time & effort to learn all that it's capable of. The effort is well worth it, though. Read the man page and practice :-)

One thing worth noting is that find's predicates are AND-ed together by default. What this means is that if you have -name '*.txt' -name '*.csv' then it will try to match files ending in .txt and .csv at the same time (which is impossible, so it won't match anything). To OR the predicates, you'd need to do something like:

find "$TEST" -maxdepth 1 -type f \( -name '*.txt' -o -name '*.csv' \) \
  -exec cat {} + > test

That will match files ending with either .txt or .csv. The OR-ed predicates are in parentheses to group them, same as in arithmetic. The whole line reads as "find files in directory $TEST to a maximum depth of 1 that are regular files AND (with names ending in either .txt OR .csv) AND execute cat on them. Redirect the output to a file called test"

Also worth noting: The {} is a placeholder for filename(s) in the -exec option. And the + at the end of the -exec option tells find to fit as many filenames as possible on each command line (so it runs cat as few times as possible). The limit is ARG_MAX, about 2 million bytes worth on a modern Linux system.

You could also use \; instead of + - this tells find to run cat ONCE per filename (so will be a lot slower, but sometimes having only one filename per run is exactly what you need. Other times, a bulk run with + is the right thing).

cas
  • 78,579