Вот:
sed -e 's/^\(\s*\)\.\+/\1/;s/\.\+\s*$//' your_file
Это распечатает измененный файл к стандартному выводу. Для записи в другой файл используйте:
sed -e 's/^\(\s*\)\.\+/\1/;s/\.\+\s*$//' your_file >new_file
Для изменения файла на месте использовать
sed -i -e 's/^\(\s*\)\.\+/\1/;s/\.\+\s*$//' your_file
Править
Из источника wc
( coreutils / src / wc.c
) в GNU coreutils (то есть версии для невстроенных Linux и Cygwin):
When counting only bytes, save some line- and word-counting
overhead. If FD is a 'regular' Unix file, using lseek is enough
to get its 'size' in bytes.
Таким образом, использование wc -c
для подсчета байтов будет эффективным.
Вы можете легко протестировать эту оптимизацию на большом файле (т. Е. На том, для чтения которого потребуется некоторое время). wc -c
для файла размером 9,9 ГБ заняла 0,015 секунды реального времени для файла, который находится на моем сервере, и я был бы рад, если бы весь файл был передан за это время, но мой гигабитный Ethernet к сожалению, не так быстро (требуется 21 секунда, чтобы скопировать этот файл в / dev / null
по сети).
]Есть время для всего, включая парсинг []ls[
]. Нет никакого портативного способа предотвратить []ls[
] от искажения имен файлов, но когда вас интересуют только некоторые метаданные об одном файле, это нормально.[
filesize () {
LC_ALL=C ls -dn -- "$1" | awk 'NR==1 {print $5}'
}
]
[]Это работает на всех системах, совместимых с []POSIX[] с расширением []XSI[]. Он работает с BusyBox, который понимает []-n[
], но не []-o[
]. Опция []-n[
] заставляет пользовательские и групповые столбцы содержать числовые значения (UID и GID), а не имена (которые могут содержать пробелы в некоторых системах, что делает разбор столбцов ненадежным). Я не думаю, что []LC_ALL[
] необходима, так как на эту часть вывода не должны влиять локали, но там может быть реализация, которая делает что-то странное, например, печатает размеры согласно []LC_NUMERIC[
], и это не повредит. [
]Если вам нужна только переносимость между системами, где можно установить zsh (который поставляется в комплекте с OSX), вы можете использовать zsh's [][]zstat[
][]:[
zmodload -F zsh/stat b:zstat
filesize () {
zstat +size -- $1
}
] я исключаю stat
и perl
, которые не являются POSIX, поэтому более вероятно, что они отсутствуют, чем ls
и awk
.
Я тоже исключаю wc
, поскольку в то время как реализация GNU wc
оптимизирована, когда используется вариант -c
, вы не должны полагаться на то, что он будет присутствовать для портативного сценария. Более того, некоторые нестандартные -c
могут возвращать количество символов -c, которое не обязательно совпадает с количеством байт -c в зависимости от локали.
В этом случае решение основано только на стандартных утилитах, которые сообщают размер файла в качестве аргумента:
filesize() {
[ -f "$1" ] && ls -dnL -- "$1" | awk '{print $5;exit}' || { echo 0; return 1; }
}
Остерегайтесь, однако, что сообщенный размер может быть либо больше, либо меньше фактического размера содержимого файла на диске, в зависимости от используемой файловой системы, поддержки разреженных файлов, а также таких опций, как сжатие или дедупликация.
Чем проще, тем портативнее может быть perl
:
filesize() {
file="$1"
if [ -e "$file" ]; then
size="$(perl -e 'print -s shift' "$file")"
printf '%s\n' "$size"
return 0
else
printf "0\n"
return -1
fi
}
Думаю, тебе стоит использовать это. Как я только что узнал, это стандартная утилита POSIX-specified .
du
Опции, указанные в POSIX, включают:
Утилита du должна соответствовать XBD Utility Syntax Guidelines .
Поддерживаются следующие опции:
-a
.
Кроме вывода по умолчанию, сообщите размер каждого файла, не относящегося к директории типа в файловой иерархии, корни которой лежат в указанном файле. Независимо от наличия опции -a, в списке всегда должны быть указаны недиректории, заданные в качестве файловых операндов. -H
Если в командной строке указана символическая ссылка, то du считает размер файла или иерархии файлов, на которые ссылается ссылка. -k
Запишите размер файлов в единицах измерения 1024 байта, а не в единицах измерения по умолчанию 512 байт. -L
Если символическая ссылка указана в командной строке или встречается во время обхода файловой иерархии, то du считает размер файла или файловой иерархии, на которые ссылается ссылка. -s
Вместо вывода по умолчанию сообщайте только общую сумму по каждому из указанных файлов. -x
При оценке размеров файлов оценивайте только те файлы, которые имеют то же устройство, что и файл, указанный файловым операндом.
Указание более чем одной из взаимоисключающих опций -H и -L не считается ошибкой. Последняя указанная опция определяет поведение утилиты. Проблема заключается в том, что она не сообщает о размере файла, а сообщает на disk-usage . Это разные понятия, и различия зависят от файловой системы. Если вы хотите получить размер файлов для набора файлов, вы можете использовать что-то вроде:
{ echo
/usr/bin/ls -ndL .//*
} | sed '/\n/P;//D;N
\|//|s|\n|/&/|
$s|$|/|;s| .//|/\
/|;2!P;D'
Это довольно простой бит sed
, который поддерживает двухстрочное адресное окно на выходе ls
. Он работает, скользя по своему входу - всегда P
прокручивая затем D
поднимая самую старую из двух строк в своем шаблоне, а затем вытягивая N
ext input line, чтобы заменить его. По сути, это однострочный взгляд.
У него есть некоторые существенные недостатки в том виде, как они написаны. Например, для собственного удобства я избегал работы с ls
-> linkpath
и вместо этого использовал опцию -Ls
, которая заставляет ls
сообщать о цели соединения, а не о самом соединении. Она также предполагает только глобусы текущего каталога. Это зависит от /
not происходящего в именах файлов - потому что это разделитель. На самом деле это довольно часто встречается - вы cd
попадаете в каталог и cd -
отступаете.
Все это может быть обработано, может быть, в несколько строк или больше, но это всего лишь демонстрация.
Ключевой компонент здесь - и причина просмотра - вот этот бит:
\|//|s|\n|/&/|
Когда самая новая линия в пространстве шаблонов содержит строку .//
добавьте /
к хвосту самой старой линии и вставьте /
в голову самой новой. Затем я также заменяю .//
на другой \n
швеллер и еще два швеллера с линейным разделением.
И вот это:
drwxr-xr-x 1 1000 1000 6 Aug 4 14:40 .//dir*
drwxr-xr-x 1 1000 1000 0 Aug 4 14:40 .//dir1
drwxr-xr-x 1 1000 1000 6 Aug 8 17:34 .//dir2
drwxr-xr-x 1 1000 1000 22 Aug 10 18:12 .//dir3
drwxr-xr-x 1 1000 1000 16 Jul 11 21:59 .//new
-rw-r--r-- 1 1000 1000 8 Aug 20 11:32 .//newfile
-rw-r--r-- 1 1000 1000 0 Jul 6 11:24 .//new
file
-rw-r--r-- 1 1000 1000 0 Jul 6 11:24 .//new
file
link
становится таким:
/drwxr-xr-x 1 1000 1000 6 Aug 4 14:40/
/dir*/
/drwxr-xr-x 1 1000 1000 0 Aug 4 14:40/
/dir1/
/drwxr-xr-x 1 1000 1000 6 Aug 8 17:34/
/dir2/
/drwxr-xr-x 1 1000 1000 22 Aug 10 18:12/
/dir3/
/drwxr-xr-x 1 1000 1000 16 Jul 11 21:59/
/new/
/-rw-r--r-- 1 1000 1000 8 Aug 20 11:32/
/newfile/
/-rw-r--r-- 1 1000 1000 0 Jul 6 11:24/
/new
file/
/-rw-r--r-- 1 1000 1000 0 Jul 6 11:24/
/new
file
link/
Но что это за польза, верно? Ну, это все меняет:
IFS=/; set -f; set $(set +f
{ echo
/usr/bin/ls -ndL .//*
}| sed '/\n/P;//D;N
\|//|s|\n|/&/|
$s|$|/|;s| .//|/\
/|;2!P;D'
)
unset IFS
while [ -n "$2" ]
do printf 'Type :\t <%.1s>\tSize :\t %.0s%.0s%.0s<%d>%.0s%.0s%.0s\nFile :\t %s\n' \
$2 "<$4>"
shift 4; done
Type : <d> Size : <6>
File : <dir*>
Type : <d> Size : <0>
File : <dir1>
Type : <d> Size : <6>
File : <dir2>
Type : <d> Size : <22>
File : <dir3>
Type : <d> Size : <16>
File : <new>
Type : <-> Size : <8>
File : <newfile>
Type : <-> Size : <0>
File : <new
file>
Type : <-> Size : <0>
File : <new
file
link>