This works even with spaces and non ascii characters, both inside the text file and the filenames, without using temp files:
infile:
# new file text in file1 blabla # new file text in file2 # new file text in file3 $//*+\ s # new file 4! aaaaaaaaa i^ # new file #¬}}{][|\~@
The awk command must be provided with the filenames as individual arguments, using single quotes so does not shell expand (double quotes), in this split.sh script:
awk -v file="0" ' BEGIN { print "AWK arguments:" for (i = 0; i < ARGC; i++){ ARRAY[i] = ARGV[i] print "\047"ARRAY[i]"\047" if (i > 1){ ARGV[i] = "" } } print "Writing:" } !/^# new file$/{ print "writing to: " "\047"ARRAY[file+1]"\047" print $0 >> ARRAY[file+1] } /^# new file$/{ close(file) ++file print "writing to: " "\047"ARRAY[file+1]"\047" print $0 > ARRAY[file+1] } ' 'infile' '1.txt' '2.txt' '3.txt' 'file $_%.txt' '&file _.txt'
The console looks like this:
AWK arguments: 'awk' 'infile' '1.txt' '2.txt' '3.txt' 'file $_%.txt' '&file _.txt' Writing: writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '2.txt' writing to: '2.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: 'file $_%.txt' writing to: 'file $_%.txt' writing to: 'file $_%.txt' writing to: 'file $_%.txt' writing to: '&file _.txt' writing to: '&file _.txt' writing to: '&file _.txt'
If the arguments are passed as the output from another command (files must exist previously in the filesystem):
' $(ls infile | tr '\n' ' ' ; ls *.txt)
it splits the arguments by the space:
AWK arguments: 'awk' 'infile' '&file' '_.txt' '1.txt' '2.txt' '3.txt' '_.txt' 'file' '$_%.txt' Writing: writing to: '&file' writing to: '&file' writing to: '&file' writing to: '&file' writing to: '_.txt' writing to: '_.txt' writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '1.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt'
To solve that pass the arguments as an array to awk, separated by a newline and not a space, with this split.sh script:
array=(infile *.txt) awk -v file="0" ' BEGIN { print "AWK arguments:" for (i = 0; i < ARGC; i++){ ARRAY[i] = ARGV[i] print "\047"ARRAY[i]"\047" if (i > 1){ ARGV[i] = "" } } print "Writing:" } !/^# new file$/{ print "writing to: " "\047"ARRAY[file+1]"\047" print $0 >> ARRAY[file+1] } /^# new file$/{ close(file) ++file print "writing to: " "\047"ARRAY[file+1]"\047" print $0 > ARRAY[file+1] } ' "${array[@]}"
Now the result is:
AWK arguments: 'awk' 'infile' '&file _.txt' '1.txt' '2.txt' '3.txt' 'file $_%.txt' Writing: writing to: '&file _.txt' writing to: '&file _.txt' writing to: '&file _.txt' writing to: '&file _.txt' writing to: '1.txt' writing to: '1.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '2.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: '3.txt' writing to: 'file $_%.txt' writing to: 'file $_%.txt' writing to: 'file $_%.txt'
The number of files to write to, must be at least the same as splits which will be performed. If more, the rest will be ignored.