Skip to main content
busybox's awk only supports length(), not length
Source Link
user313992
user313992

Using awk to find the offset of the pattern, and dd to truncate the file at that point and append the new trailer:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo"printf \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           exit
       }
       {l+=length+1l+=length()+1}
    ' {} \;
}

truncatoo '/END DATA/' 'NEW END\n' file.txt
truncatoo '/END DATA/' 'NEW END\n' . -type f -name '*.txt'

With an awk implementation which supports nextfile (gawk, bwk, some versions of mawk [1]), that could be done more efficiently by passing batches of files to awk:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo"printf \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1l+=length()+1}
    ' {} +
}
$ truncatoo '/END DATA/' 'NEW END' file.txt
$ truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'

$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT'CUT\n' "$file"; cat "$file"
1
2
3
4
5
6
EOTCUT

Instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

[1]: according to the GNU awk manual, it should be supported in mawk too. However, the older version of mawk from Debian 10 does not support it.

Using awk to find the offset of the pattern, and dd to truncate the file at that point and append the new trailer:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           exit
       }
       {l+=length+1}
    ' {} \;
}

With an awk implementation which supports nextfile (gawk, bwk, some versions of mawk), that could be done more efficiently by passing batches of files to awk:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}
$ truncatoo '/END DATA/' 'NEW END' file.txt
$ truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'

$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

Instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

Using awk to find the offset of the pattern, and dd to truncate the file at that point and append the new trailer:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("printf \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           exit
       }
       {l+=length()+1}
    ' {} \;
}

truncatoo '/END DATA/' 'NEW END\n' file.txt
truncatoo '/END DATA/' 'NEW END\n' . -type f -name '*.txt'

With an awk implementation which supports nextfile (gawk, bwk, some versions of mawk [1]), that could be done more efficiently by passing batches of files to awk:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("printf \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length()+1}
    ' {} +
}
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ 'CUT\n' "$file"; cat "$file"
1
2
3
4
5
6
CUT

Instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

[1]: according to the GNU awk manual, it should be supported in mawk too. However, the older version of mawk from Debian 10 does not support it.

Post Undeleted by CommunityBot
added 404 characters in body
Source Link
user313992
user313992

With standardUsing awk to find the offset of the pattern, and using dd to truncate the file, since awk doesn't support seek or truncate. at that point and append the new trailer:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           exit
       }
       {l+=length+1}
    ' {} \;
}

Instead ofWith an awk implementation which supports ddnextfile, (truncategawk could be used on Linux, and instead of the icky 2>/dev/nullbwk, some versions of status=noxfermawk), that could be used with dd implementations which support it.

The quoting kludge and environment variablesdone more efficiently by passing is a mess, it could use some improvement.

TODO: nextfile doesn't work right in Debian's 10 mawkbatches of files to awk:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}
 
$ truncatoo '/END DATA/' 'NEW END' file.txt
$ truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
  
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

Instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

With standard awk, and using dd to truncate the file, since awk doesn't support seek or truncate.

Instead of dd, truncate could be used on Linux, and instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

TODO: nextfile doesn't work right in Debian's 10 mawk

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}
 
truncatoo '/END DATA/' 'NEW END' file.txt
truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
 $ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

Using awk to find the offset of the pattern, and dd to truncate the file at that point and append the new trailer:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           exit
       }
       {l+=length+1}
    ' {} \;
}

With an awk implementation which supports nextfile (gawk, bwk, some versions of mawk), that could be done more efficiently by passing batches of files to awk:

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}
$ truncatoo '/END DATA/' 'NEW END' file.txt
$ truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
 
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

Instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

added 59 characters in body
Source Link
user313992
user313992

With standard awk, and using dd to truncate the file, since awk doesn't support seek or truncate.

Instead of dd, truncate could be used on Linux, and instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

TODO: nextfile doesn't work right in Debian's 10 mawk

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}

truncatoo '/END DATA/' 'NEW END' file.txt
truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

With standard awk, and using dd to truncate the file, since awk doesn't support seek or truncate.

Instead of dd, truncate could be used on Linux, and instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}

truncatoo '/END DATA/' 'NEW END' file.txt
truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT

With standard awk, and using dd to truncate the file, since awk doesn't support seek or truncate.

Instead of dd, truncate could be used on Linux, and instead of the icky 2>/dev/null status=noxfer could be used with dd implementations which support it.

The quoting kludge and environment variables passing is a mess, it could use some improvement.

TODO: nextfile doesn't work right in Debian's 10 mawk

# usage truncatoo pattern new_end find_args ...
truncatoo(){
    pat=$1; shift; tail=$1; shift
    LC_CTYPE=C TAIL=$tail find "$@" -exec awk -v q="'" "$pat"'{
           gsub(q,q"\\"q q,FILENAME);
           system("echo \"$TAIL\" | dd bs="l" seek=1 of="q FILENAME q" 2>/dev/null");
           l=0; nextfile
       }
       {l+=length+1}
    ' {} +
}

truncatoo '/END DATA/' 'NEW END' file.txt
truncatoo '/END DATA/' 'NEW END' . -type f -name '*.txt'
$ file="a'b\$q  * r"; seq 1 100 >"$file"
$ truncatoo /7/ EOT "$file"; cat "$file"
1
2
3
4
5
6
EOT
fix it to work with multiple files
Source Link
user313992
user313992
Loading
Post Deleted by CommunityBot
Source Link
user313992
user313992
Loading
Post Made Community Wiki by user313992