假设我有一个7字节的文件,名为test.dat。 如果我用HEX编辑器打开test.dat,代码将是
1F 2E 3D 4C 5B 6A 70
(代码没有重大意义。只是为了测试!)
现在,我想要生成7000000字节文件,它可以被称为milliontest.dat,通过重复这个十六进制代码1000000次。欢迎批量或bash。
感谢您帮助我!
答案 0 :(得分:5)
Easy-Way
@echo off
(
For /l %%n in (1,1,1000000) do copy milliontest.dat /B + test.dat /B milliontest.dat /B
) >nul 2>nul
快速方式
这项工作非常快(在我的旧机器上0.2秒),它是纯dos批量解决方案。
@echo off
setlocal EnableDelayedExpansion
>test.dat set /p ".=1234567" <nul
copy test.dat /B tmp.dat >nul
set Times=1000000
(
for /l %%n in (1,1,31) do (
set /A "bit=Times %% 2, Times/=2"
If !bit! equ 1 copy milliontest.dat /B + tmp.dat /B milliontest.dat /B
if !Times! gtr 0 (
copy tmp.dat /B + tmp.dat /B tot.dat /B
del tmp.dat
ren tot.dat tmp.dat
) >nul 2>nul
)
) > milliontest.dat
del tmp.dat
exit /b
正如Aacini所说,我解释了这种方法。这个方法如何将文件test.dat的字节乘以一百万。这使用Bynary Multiplication。
&#34;在基数2中,长乘法减少到几乎无足轻重的操作。 对于每个&#39; 1&#39;乘法器中的位,移位被乘数 适当的数量,然后将移位的值相加。取决于 计算机处理器架构和乘数的选择,它可能是 使用硬件位移和加法编码此算法的速度更快 而不是依赖于乘法指令,当乘数 是固定的,所需的添加数量很少。&#34;
更简单的方法
这样可以减少复制命令的数量。每10个副本重用一次结果。 为了达到结果,这个使用6个周期,一个百万,因为零的数量是六个。
copy test.dat /B tmp.dat >nul /B
copy tmp.dat /B milliontest.dat /B
For /l %%d in (1,1,6) do (
For /l %%n in (1,1,9) do copy milliontest.dat /B + tmp.dat /B milliontest.dat /B
copy milliontest.dat /B tmp.dat /B
) >nul
为了加倍文件我已探测使用:
type tmp.dat>>tmp.dat
但是出现错误,而不是我使用COPY。
编辑: 用COPY Always替换TYPE命令。 TYPE适用于文本文件。
答案 1 :(得分:0)
@echo off
setlocal
set "hex_string=1F 2E 3D 4C 5B 6A 70"
(for /l %%# in (1;1;1000000) do (
(break|set /p=%hex_string% )
))>>hex_file
这会将十六进制字符串打印到文件1000000次。如果要将文件读取为十六进制,可以检查certutil
答案 2 :(得分:0)
使用Guxutils sed
for /L %a in (1,1,999999) do @(sed.exe -ri "s/(.{7})(.*)/\1\2\1/" "test.dat")
sed.exe -ri "s/(.{7})(.*)/\1\2\1/" "test.dat"
将获得test.dat中的前7个HEX,其余的HEX并将前7个HEX添加到最后。然后替换test.dat。
但是这会将test.dat重新写入磁盘999999次。
<强>更新强>
@echo off
setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,100) do (set "s_1=!s_1!+")
for /L %%a in (1,1,3) do (
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
)
exit /b
更新的代码可以快速执行功能,只能写入磁盘3次。
或者 @echo关闭 setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,1000) do (set "s_1=!s_1!+")
for /L %%a in (1,1,2) do (
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
)
exit /b
这将写2次。
但是根据命令长度的限制。它不能以
运行set "s_1="
for /L %%a in (1,1,1000000) do (set "s_1=!s_1!+")
"%sed_path%\sed" -ri "s/.*/%s_1:+=&%/" "test.dat"
exit /b
如果“test.dat”必须保留,
@echo off
setlocal enabledelayedexpansion
set "s_1="
for /L %%a in (1,1,1000) do (set "s_1=!s_1!+")
for /L %%a in (1,1,2) do (
"%sed_path%\sed" -r "s/.*/%s_1:+=&%/" "test.dat"
)>>test2.dat
exit /b
答案 3 :(得分:0)
纯批量解决方案可能相当慢。
您可以使用我的JREPL.BAT regex text processing utility来实现简单快速的解决方案。它是纯脚本(混合JScript /批处理),可以在XP之后的任何Windows机器上本机运行。可以从命令行通过jrepl /?
或jrepl /??
获取完整文档以获取分页输出。
jrepl ".*" "Array(1000000+1).join($0)" /m /j /f "test.dat" /o "millionTest.dat"
答案 4 :(得分:0)
这个问题有点不清楚。我认为关于HEX的东西是无关紧要的,并且要求是复制&#39; test.dat&#39;进入&#39; milliontest.dat&#39;一百万次。使用cat
和xargs
在Bash中执行相对有效的方法是:
for i in {1..1000000} ; do echo test.dat ; done | xargs cat >milliontest.dat
答案 5 :(得分:0)
这个Bash代码概括了Einstein1969提供的两个解决方案:
readonly srcfile=test.dat
readonly multiplier=1000000
readonly destfile=milliontest.dat
readonly base=100
readonly tmp1=$(mktemp)
readonly tmp2=$(mktemp)
declare -i mult=multiplier
curr_src=$srcfile
curr_dest=$tmp1
# 'curr_src_list' is an array containing $base copies of the current source
# file path
declare -a curr_src_list="( {1..$base} )"
curr_src_list=( "${curr_src_list[@]/*/$curr_src}" )
# Initialize the (final) destination file
echo -n > "$destfile"
# Exit immediately if the multiplier is zero or the source file is empty
(( mult == 0 )) && exit 0
[[ -s $srcfile ]] || exit 0
declare -i rem scale
while (( mult > 0 )) ; do
# Loop invariant: (final $destfile) == mult * $curr_src + $destfile
rem=mult%base
div=mult/base
if (( rem != 0 )) ; then
cat -- "${curr_src_list[@]:0:rem}" >> "$destfile"
mult=mult-rem
elif (( mult == base )) ; then
cat -- "${curr_src_list[@]}" >> "$destfile"
mult=0
else
# Determine number ($scale) by which to duplicate $curr_src and divide
# $multiplier.
if (( div < base )) ; then
# Will finish on the next iteration. Copy a smaller amount to
# the temporary file now to minimize wasted copying.
scale=div
mult=base
else
scale=base
mult=div
fi
cat -- "${curr_src_list[@]:0:scale}" > "$curr_dest"
# Current destination becomes new current source
curr_src=$curr_dest
curr_src_list=( "${curr_src_list[@]/*/$curr_src}" )
# Other temporary file becomes new current destination
[[ $curr_dest == "$tmp1" ]] && curr_dest=$tmp2 || curr_dest=$tmp1
fi
done
rm -f -- "$tmp1" "$tmp2"
设置base=2
给出&#34;快速方式&#34;。设置base=10
会提供更简单的方式&#34;。设置base=100
,如上面的代码所示,意味着只需3 cat
个操作即可生成所需的输出。它在古老的Linux系统上以大约百分之三秒的速度运行。当multiplier
设置为十亿(1000000000)时,它运行cat
5次,并在一个相当现代的Linux系统上以超过11秒的时间完成。
该算法基本上是标准的长乘法算法。代码可能稍微简单一些,但有时会将更多数据复制到临时文件。此代码(带base=100
)最多应复制1%到临时文件