Вы можете попробовать записать на C:
#include
#include
#include
int main(){
char buf[BUFSIZ];
int nread;
size_t nfound=0;
while((nread=read(0, buf, BUFSIZ))>0){
char const* p;
for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}
}
if(nread<0) { perror("Error"); return 1; }
printf("%lu\n", nfound);
return 0;
}
Сохранить, например, wcl.c
, скомпилировать, например, с помощью gcc wcl.c -O2 -o wcl
и запустить с
Это обнаруживает символы новой строки, разбросанные в файле размером 1 ГБ в моей системе примерно за 370 мс (повторные прогоны).
(Увеличение размера буфера немного увеличивает время, чего и следовало ожидать - BUFSIZ должен быть близок к оптимальному).
Это очень похоже на ~ 380 мс Я получаю от wc -l
.
Mmaping дает мне лучшее время примерно 280 мс , но, конечно, имеет ограничение, заключающееся в том, что он ограничен реальными файлами (без FIFOS, без ввода терминала и т. Д.):
#include
#include
#include
#include
#include
#include
int main(){
struct stat sbuf;
if(fstat(0, &sbuf)<0){ perror("Can't stat stdin"); return 1; }
char* buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, 0/*stdin*/, 0/*offset*/);
if(buf == MAP_FAILED){ perror("Mmap error"); return 1; }
size_t nread = sbuf.st_size, nfound=0;
char const* p;
for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}
printf("%lu\n", nfound);
return 0;
}
Я создал свой тестовый файл с:
$ dd if=/dev/zero of=file bs=1M count=1042
и добавлены некоторые тестовые символы новой строки с:
$ echo >> 1GB
и шестнадцатеричный редактор.
Вот довольно деструктивный метод :заменить относительные ссылки абсолютными ссылками:
cd foo
for f in *; do
if [[ -h $f ]] # True if file is a symbolic link.
then
abs=$(readlink -f "$f") && rm "$f" && ln -s "$abs" "$f"
fi
done
Наконец-то я написал решение и разместил его на Github:
https://github.com/minTaqa/mvrel
В настоящее время он не так гибок, как «mv», поскольку разрешены только два аргумента, а второй аргумент должен быть каталогом. Тем не менее, я нашел его полезным для перемещения чего-то, что имеет много относительных символических ссылок. Я хотел убедиться, что он может работать с пробелами, символами новой строки и прочей ерундой в именах файлов, так что это также был шанс для меня узнать о Bats, совместимом с TAP -фреймворке для тестирования, написанном на Bash, куда я поместил некоторые модули. тесты, чтобы убедиться, что все работает.
Сам скрипт тоже написан на Bash. Я думал, что это будет самый простой и переносимый язык для этой задачи, но в итоге мне пришлось обойти такие вещи, как тот факт, что подстановка команд удаляет завершающие символы новой строки(проблема, если у вас есть имена файлов с завершающими символами новой строки, что в основном теоретические, но все же раздражающие ). Затем идут find... -print0
и IFS= read -rd ''
, а также множество кавычек и " --" аргументов --, которые не нужны в скриптовом языке немного более низкого -уровня, таком как Perl. Я также не стал бы выполнять манипуляции со строками путем раскрытия параметров в Perl. В любом случае, вы можете переписать его на Perl или даже на C, если хотите; как бы то ни было, в Bash он достаточно короткий.