The same command: echo 1 > filename creates different filenames:
$ sh -c 'echo $LANG >=с=.sh' && ls *.sh | od -c
0000000   = 321   =   .   s   h  \n
0000007
and
$ bash -c 'echo $LANG >=с=.bash' && ls *.bash | od -c
0000000   = 321 201   =   .   b   a   s   h  \n
0000012
Where с is the U+0441 character — CYRILLIC SMALL LETTER ES. It is clear that sh eats the second byte in the utf-8 encoding.
$ ls *sh
=?=.sh  =с=.bash
$LANG in both cases is:
$ cat *sh
en_US.utf8
en_US.utf8
sh is linked to dash on my system:
$ apt-cache show dash | grep -i version
Version: 0.5.5.1-7ubuntu1
stty iutf8 is set.
Is there any setting that allows dash not to mangle multi-byte characters?
I don't see any mentions about character encoding in the manual:
$ man dash | grep -i encoding
$ man dash | grep -Pi 'multi.*byte'
Update
The second byte '\201' of the 'с' character in utf-8 encoding is
-127 as signed char (or 129 as unsigned char) in C.
The search in the source code (apt-get source dash) for -127 results in:
src/parser.h:38:#define CTL_FIRST -127      /* first 'special' character */
src/parser.h:39:#define CTLESC -127     /* escape next character */
Search for CTLESC leads to rmescapes() macros that leads to the
following fragment from src/expand.c:expandarg():
/*
 * TODO - EXP_REDIR
 */
if (flag & EXP_FULL) {
    ifsbreakup(p, &exparg);
    *exparg.lastp = NULL;
    exparg.lastp = &exparg.list;
    expandmeta(exparg.list, flag);
} else {
    if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
        rmescapes(p);
    sp = (struct strlist *)stalloc(sizeof (struct strlist));
    sp->text = p;
    *exparg.lastp = sp;
    exparg.lastp = &sp->next;
}
TODO and XXX hints that a more recent version might
help. debian/dash.README.source points to:
$ git clone http://smarden.org/git/dash.git/
$ cd dash
There are two branches:
$ git br
* debian-sid
  release+patches
On debian-sid the escape byte is removed. On the release+patches
branch grep finds the missing byte.
$ ./configure
$ make && rm *.dash -f; ./dash -c 'echo 1 >fсf.dash' && 
> ls *.dash | od -c | grep 201
git diff debian-sid...release+patches shows that rmescapes() was
removed in release-patches:
diff --git a/src/expand.c b/src/expand.c
index e4c4c8b..f2f964c 100644
--- a/src/expand.c
+++ b/src/expand.c
...
@@ -213,8 +210,6 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
                exparg.lastp = &exparg.list;
                expandmeta(exparg.list, flag);
        } else {
-               if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
-                       rmescapes(p);
                sp = (struct strlist *)stalloc(sizeof (struct strlist));
                sp->text = p;
                *exparg.lastp = sp;
@@ -412,7 +407,7 @@ lose:
 }
It is unclear whether these changes will be included in dash 0.5.6.1 on Ubuntu.
For now the only way to make the command:
$ sh -c 'echo 1 >fсf.dash' &&  ls *.dash | od -c | grep 201
to work is to reconfigure sh back to bash:
$ sudo dpkg-reconfigure dash
Are there other alternatives?
                        
Of the several shells (or versions) I tried, only Dash and Busybox Ash failed.
The contents were all the same.
From
man dash:POSIX says:
and