Double hashes inside macro definition?

Each \def...{body} reduces the number of hash characters to half in its internal representation in the body. Each \toks<num>={body} keeps the number of hash characters. Each \write or \scantokens doubles the number of hash characters.

\def\macro{This is some hashes: ##} % we have one # in internal representation

\scantokens\expandafter{\expandafter\toks\expandafter0\expandafter{\macro}} 
% \scantotkens does \write, we have two internal #, \toks0 keeps two #.

\edef\newmacro{\the\toks0}  % this keeps two # in internal representation

\message{\meaning\macro, \meaning\newmacro} % \meaning doubles the #, so we see:
%             ##              ####
% because there is:
%             #               ##     in internal representation

\bye

An l3regex approach:

\regex_replace_all:nnN { (\cP\#)+ } { \1\1 } \macro

A full example:

\documentclass{article}

\begin{document}
\ExplSyntaxOn

\tl_new:N \macro
\tl_set:Nn \macro {\def\y{\def\z##1{<##1>}}}

% before doubling the hash mark
\cs_generate_variant:Nn \cs_new:Npn {Npo}
\macro \y \z{abc} % output "<abc>"
\par

% after doubling the hash mark
\regex_replace_all:nnN { (\cP#)+ } { \1\1 } \macro
\cs_new:Npo \x {\l_test_tl}
\x\y\z{abc} % output "<abc>"

\ExplSyntaxOff
\end{document}


You can use \edef with \unexpanded:

\documentclass{article}
\de\documentclass{article}
\def\safedef#1#2{\edef#1{\unexpanded{#2}}}
\begin{document}
\def\macro{This is some hashes: ##}
\safedef\Macro{This is some hashes: ##}
\typeout{\macro -\Macro}
\end{document}

shows

This is some hashes: ##-This is some hashes: ####