The files are named file00 through file99 (hundred files). They are all in the same directory. How do I grab all the hundred files and delete the first 10 lines from each file? I am using CentOS 7.
- 175
4 Answers
This will delete the first ten lines from all files whose names range from file00 to file99:
sed -i.bak -n '11,$p' file[0-9][0-9]
This might require GNU sed, which is known as gsed on OSX. For other seds, try:
find file[0-9][0-9] -maxdepth 0 -type f -exec sed -i.bak -n '11,$p' {} \;
How it works:
-i.baktells sed to modify the files in-place, creating a backup file with the .bak extension-ntells sed not to print any lines unless we explicitly ask it to.11,$ptells sed to print lines starting with line number 11 and continuing to the last line (denoted$) in the file.file[0-9][0-9]is a shell glob that will expand to match all files whose names consist offilefollowed by two digits.
Alternative
The logic can be inverted. Instead of explicitly printing the lines 11 and after, we could (hat tip: JigglyNaga) delete the first ten lines:
sed -i.bak '1,10d' file[0-9][0-9]
- 74,655
Using a simple loop in bash (or any Bourne-like shell) and GNU or BSD sed:
for f in file[0-9][0-9]; do
sed -i '.bak' '1,10d' "$f"
done
The sed editing script 1,10d will delete lines 1 through to 10 from the input stream. The other lines will be outputted. With -i '.bak' we ask sed to do the editing in-line in the file, but to back up the original with a .bak suffix.
Alternatives with explicit looping (allows for sub-intervals, ksh93, bash or zsh syntax):
for (( i = 0; i < 100; ++i )); do
f="$( printf "file%02d" "$i" )"
sed -i '.bak' '1,10d' "$f"
done
Using ksh93 or zsh, another way:
typeset -Z 2 j
for (( i = 0; i < 100; ++i )); do
j=$i
sed -i '.bak' '1,10d' "file$j"
done
The typeset -Z 2 j will force $j into a zero-filled number of width 2. We don't want to typeset i in this way as its value would turn into 00 once it reached 100, effectively turning the loop into an infinite loop. That's for ksh93, zsh seems able to handle it as it apparently uses the value before submitting it to the formatting.
- 333,661
-
1Good catch about ksh93 and i=100 becoming as opposed to expanding to 00. Compare
zsh -c 'typeset -Z2 i; i=100; echo "$i $((i))"'with the same withksh93. – Stéphane Chazelas Jul 31 '16 at 16:22 -
-
Another way to do ranges / steps:
for i in {0..9}{2,4,6,8,0} 100;do ..., orseqFor a one-off by hand, it's generally not a problem to generate a filename that you know won't exist (like00). – Peter Cordes Jul 31 '16 at 17:20
To avoid creating temporary files or affecting the permissions, ownership or other attributes of the files, with ksh93:
for f in file{2}([0-9]); do
tail -n +11 < "$f" 1<>; "$f"
done
The <>; redirection operator acts like <> (open in read+write mode), except that the shell truncates the file upon the command exiting successfully at the position the command left it.
So, we're basically overwriting the file over itself.
- 544,893
If you prefer a bash loop:
for f in file[0-9][0-9]; do
tail -n +11 "$f" > tmp &&
mv -f tmp "$f"
done
- 544,893
- 14,916
sedresets the line numbers inbetween files. (not on OS X) – Kusalananda Jul 31 '16 at 07:36-nflag with1,10d. – JigglyNaga Jul 31 '16 at 07:361,10dapproach. – John1024 Jul 31 '16 at 07:41file34is a link. The op has not specified any requirements about this – sjsam Jul 31 '16 at 07:42findis required to be GNUfind, or anotherfindthat understands-maxdepth. Most (on the free Unices) actually do, and the OP is on Linux, so it's prolly ok. – Kusalananda Jul 31 '16 at 07:50-maxdepthis supported not just by GNU find but also by OSX find and freeBSD find. Which versions offindare you aware of that don't support it? – John1024 Jul 31 '16 at 07:53findimplementations do support the flag. AIX, Minix, and Tru64finddoesn't. – Kusalananda Jul 31 '16 at 08:01