runtime(netrw): runtime(netrw): upstream snapshot of v178

relevant commits:
- refactor: netrw#own#Deprecate -> netrw#msg#Deprecate
- refactor: netrw#own#PathJoin -> netrw#fs#PathJoin
- fix: typos
- refactor: netrw#own#Open -> netrw#os#Open
- deprecate!: netrw#WinPath
- refactor: netrw#WinPath -> netrw#fs module
- refactor: s:ShellEscape -> netrw#os module
- refactor: s:NetrwExe -> netrw#os module
- refactor: s:NetrwGlob -> netrw#fs module
- refactor: s:NetrwGetcwd -> netrw#fs module
- refactor: s:NetrwFullPath -> netrw#fs module
- refactor: s:ComposePath -> netrw#fs module

closes: #16718

Signed-off-by: Luca Saccarola <github.e41mv@aleeas.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/Filelist b/Filelist
index 07560e5..34b1a23 100644
--- a/Filelist
+++ b/Filelist
@@ -816,7 +816,9 @@
 		runtime/pack/dist/opt/netrw/LICENSE.txt \
 		runtime/pack/dist/opt/netrw/README.md \
 		runtime/pack/dist/opt/netrw/autoload/netrw.vim \
-		runtime/pack/dist/opt/netrw/autoload/netrw/own.vim \
+		runtime/pack/dist/opt/netrw/autoload/netrw/fs.vim \
+		runtime/pack/dist/opt/netrw/autoload/netrw/os.vim \
+		runtime/pack/dist/opt/netrw/autoload/netrw/msg.vim \
 		runtime/pack/dist/opt/netrw/autoload/netrwSettings.vim \
 		runtime/pack/dist/opt/netrw/autoload/netrw_gitignore.vim \
 		runtime/pack/dist/opt/netrw/doc/netrw.txt \
diff --git a/runtime/doc/tags b/runtime/doc/tags
index aa43fb0..410807e 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -9002,6 +9002,7 @@
 netrw-ctrl-l	pi_netrw.txt	/*netrw-ctrl-l*
 netrw-ctrl-r	pi_netrw.txt	/*netrw-ctrl-r*
 netrw-ctrl_l	pi_netrw.txt	/*netrw-ctrl_l*
+netrw-curdir	pi_netrw.txt	/*netrw-curdir*
 netrw-d	pi_netrw.txt	/*netrw-d*
 netrw-del	pi_netrw.txt	/*netrw-del*
 netrw-delete	pi_netrw.txt	/*netrw-delete*
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw.vim b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
index 7131002..d2b7d41 100644
--- a/runtime/pack/dist/opt/netrw/autoload/netrw.vim
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
@@ -16,14 +16,14 @@
 
 " Load Once: {{{1
 if &cp || exists("g:loaded_netrw")
-  finish
+    finish
 endif
 
-let g:loaded_netrw = "v177"
+let g:loaded_netrw = "v178"
 
 if !has("patch-9.1.1054") && !has('nvim')
-  echoerr 'netrw needs Vim v9.1.1054'
-  finish
+    echoerr 'netrw needs Vim v9.1.1054'
+    finish
 endif
 
 let s:keepcpo= &cpo
@@ -1211,28 +1211,28 @@
     " obtain a file from local b:netrw_curdir to (local) tgtdir
     "   call Decho("obtain a file from local ".b:netrw_curdir." to ".tgtdir,'~'.expand("<slnum>"))
     if exists("b:netrw_curdir") && getcwd() != b:netrw_curdir
-      let topath= s:ComposePath(tgtdir,"")
+      let topath = netrw#fs#ComposePath(tgtdir,"")
       if has("win32")
         " transfer files one at time
         "     call Decho("transfer files one at a time",'~'.expand("<slnum>"))
         for fname in fnamelist
-          "      call Decho("system(".g:netrw_localcopycmd." ".s:ShellEscape(fname)." ".s:ShellEscape(topath).")",'~'.expand("<slnum>"))
-          call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".s:ShellEscape(fname)." ".s:ShellEscape(topath))
+          "      call Decho("system(".g:netrw_localcopycmd." ".netrw#os#Escape(fname)." ".netrw#os#Escape(topath).")",'~'.expand("<slnum>"))
+          call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".netrw#os#Escape(fname)." ".netrw#os#Escape(topath))
           if v:shell_error != 0
             call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localcopycmd<".g:netrw_localcopycmd."> to something that works",80)
-            "       call Dret("s:NetrwObtain 0 : failed: ".g:netrw_localcopycmd." ".s:ShellEscape(fname)." ".s:ShellEscape(topath))
+            "       call Dret("s:NetrwObtain 0 : failed: ".g:netrw_localcopycmd." ".netrw#os#Escape(fname)." ".netrw#os#Escape(topath))
             return
           endif
         endfor
       else
         " transfer files with one command
         "     call Decho("transfer files with one command",'~'.expand("<slnum>"))
-        let filelist= join(map(deepcopy(fnamelist),"s:ShellEscape(v:val)"))
-        "     call Decho("system(".g:netrw_localcopycmd." ".filelist." ".s:ShellEscape(topath).")",'~'.expand("<slnum>"))
-        call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".filelist." ".s:ShellEscape(topath))
+        let filelist= join(map(deepcopy(fnamelist),"netrw#os#Escape(v:val)"))
+        "     call Decho("system(".g:netrw_localcopycmd." ".filelist." ".netrw#os#Escape(topath).")",'~'.expand("<slnum>"))
+        call system(g:netrw_localcopycmd.g:netrw_localcopycmdopt." ".filelist." ".netrw#os#Escape(topath))
         if v:shell_error != 0
           call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localcopycmd<".g:netrw_localcopycmd."> to something that works",80)
-          "      call Dret("s:NetrwObtain 0 : failed: ".g:netrw_localcopycmd." ".filelist." ".s:ShellEscape(topath))
+          "      call Dret("s:NetrwObtain 0 : failed: ".g:netrw_localcopycmd." ".filelist." ".netrw#os#Escape(topath))
           return
         endif
       endif
@@ -1263,8 +1263,8 @@
       else
         let path= ""
       endif
-      let filelist= join(map(deepcopy(fnamelist),'escape(s:ShellEscape(g:netrw_machine.":".path.v:val,1)," ")'))
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_scp_cmd.s:ShellEscape(useport,1)." ".filelist." ".s:ShellEscape(tgtdir,1))
+      let filelist= join(map(deepcopy(fnamelist),'escape(netrw#os#Escape(g:netrw_machine.":".path.v:val,1)," ")'))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.netrw#os#Escape(useport,1)." ".filelist." ".netrw#os#Escape(tgtdir,1))
 
     elseif b:netrw_method == 2
       " obtain file using ftp + .netrc
@@ -1291,9 +1291,9 @@
         "      call Decho("filter input: ".getline('$'),'~'.expand("<slnum>"))
       endfor
       if exists("g:netrw_port") && g:netrw_port != ""
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
       else
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
       endif
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$" && !exists("g:netrw_quiet") && getline(1) !~ '^Trying '
@@ -1362,7 +1362,7 @@
       " -n  win32: quit being obnoxious about password
       "  Note: using "_dd to delete to the black hole register; avoids messing up @@
       NetrwKeepj norm! 1G"_dd
-      call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
+      call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$"
         "     call Decho("error<".getline(1).">",'~'.expand("<slnum>"))
@@ -1379,7 +1379,7 @@
       else
         let localfile= a:fname
       endif
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1).s:ShellEscape(localfile)." ".s:ShellEscape(tgtdir))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1).netrw#os#Escape(localfile)." ".netrw#os#Escape(tgtdir))
 
     elseif !exists("b:netrw_method") || b:netrw_method < 0
       " probably a badly formed url; protocol not recognized
@@ -1951,7 +1951,7 @@
           let uid_machine = g:netrw_machine
         endif
       endif
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".s:ShellEscape(uid_machine.":".b:netrw_fname,1)." ".s:ShellEscape(tmpfile,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".netrw#os#Escape(uid_machine.":".b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
       let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
       let b:netrw_lastfile = choice
 
@@ -1972,9 +1972,9 @@
       call setline(line("$")+1,'get "'.netrw_fname.'" '.tmpfile)
       "     call Decho("filter input: ".getline(line("$")),'~'.expand("<slnum>"))
       if exists("g:netrw_port") && g:netrw_port != ""
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
       else
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
       endif
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$" && !exists("g:netrw_quiet") && getline(1) !~ '^Trying '
@@ -2040,7 +2040,7 @@
       " -n  unix : DON'T use <.netrc>, even though it exists
       " -n  win32: quit being obnoxious about password
       NetrwKeepj norm! 1G"_dd
-      call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
+      call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$"
         "     call Decho("error<".getline(1).">",'~'.expand("<slnum>"))
@@ -2068,7 +2068,7 @@
       else
         let tmpfile_get = tmpfile
       endif
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".escape(s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1),' ')." ".s:ShellEscape(tmpfile_get,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".escape(netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1),' ')." ".netrw#os#Escape(tmpfile_get,1))
       let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
       let b:netrw_lastfile = choice
 
@@ -2088,9 +2088,9 @@
         " using g:netrw_http_cmd (usually elinks, links, curl, wget, or fetch)
         "     call Decho('using '.g:netrw_http_cmd.' (# not in b:netrw_fname<'.b:netrw_fname.">)",'~'.expand("<slnum>"))
         if exists("g:netrw_http_xcmd")
-          call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_http_cmd." ".s:ShellEscape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1)." ".g:netrw_http_xcmd." ".s:ShellEscape(tmpfile,1))
+          call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1)." ".g:netrw_http_xcmd." ".netrw#os#Escape(tmpfile,1))
         else
-          call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_http_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1))
+          call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.b:netrw_fname,1))
         endif
         let result = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
 
@@ -2101,7 +2101,7 @@
         let netrw_tag = substitute(b:netrw_fname,"^.*#","","")
         "     call Decho("netrw_html<".netrw_html.">",'~'.expand("<slnum>"))
         "     call Decho("netrw_tag <".netrw_tag.">",'~'.expand("<slnum>"))
-        call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_http_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(b:netrw_http."://".g:netrw_machine.netrw_html,1))
+        call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(b:netrw_http."://".g:netrw_machine.netrw_html,1))
         let result = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
         "     call Decho('<\s*a\s*name=\s*"'.netrw_tag.'"/','~'.expand("<slnum>"))
         exe 'NetrwKeepj norm! 1G/<\s*a\s*name=\s*"'.netrw_tag.'"/'."\<CR>"
@@ -2121,7 +2121,7 @@
         return
       endif
       if g:netrw_dav_cmd =~ "curl"
-        call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_dav_cmd." ".s:ShellEscape("dav://".g:netrw_machine.b:netrw_fname,1)." ".s:ShellEscape(tmpfile,1))
+        call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_dav_cmd." ".netrw#os#Escape("dav://".g:netrw_machine.b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
       else
         " Construct execution string (four lines) which will be passed through filter
         let netrw_fname= escape(b:netrw_fname,g:netrw_fname_escape)
@@ -2140,7 +2140,7 @@
 
         " perform cadaver operation:
         NetrwKeepj norm! 1G"_dd
-        call s:NetrwExe(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
+        call netrw#os#Execute(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
         keepj bd!
       endif
       let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
@@ -2150,7 +2150,7 @@
     " NetRead: (rsync) NetRead Method #7 {{{3
     elseif     b:netrw_method  == 7
       "    call Decho("read via rsync (method #7)",'~'.expand("<slnum>"))
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".s:ShellEscape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1)." ".s:ShellEscape(tmpfile,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".netrw#os#Escape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1)." ".netrw#os#Escape(tmpfile,1))
       let result           = s:NetrwGetFile(readcmd,tmpfile, b:netrw_method)
       let b:netrw_lastfile = choice
 
@@ -2174,9 +2174,9 @@
       "    call Decho("read via fetch for ".netrw_option,'~'.expand("<slnum>"))
 
       if exists("g:netrw_uid") && g:netrw_uid != "" && exists("s:netrw_passwd") && s:netrw_passwd != ""
-        call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(netrw_option."://".g:netrw_uid.':'.s:netrw_passwd.'@'.g:netrw_machine."/".b:netrw_fname,1))
+        call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(netrw_option."://".g:netrw_uid.':'.s:netrw_passwd.'@'.g:netrw_machine."/".b:netrw_fname,1))
       else
-        call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(netrw_option."://".g:netrw_machine."/".b:netrw_fname,1))
+        call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_fetch_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(netrw_option."://".g:netrw_machine."/".b:netrw_fname,1))
       endif
 
       let result          = s:NetrwGetFile(readcmd,tmpfile, b:netrw_method)
@@ -2188,7 +2188,7 @@
     " NetRead: (sftp) NetRead Method #9 {{{3
     elseif     b:netrw_method  == 9
       "    call Decho("read via sftp (method #9)",'~'.expand("<slnum>"))
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1)." ".tmpfile)
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_sftp_cmd." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1)." ".tmpfile)
       let result          = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
       let b:netrw_lastfile = choice
 
@@ -2196,7 +2196,7 @@
     " NetRead: (file) NetRead Method #10 {{{3
     elseif      b:netrw_method == 10 && exists("g:netrw_file_cmd")
       "   "    call Decho("read via ".b:netrw_file_cmd." (method #10)",'~'.expand("<slnum>"))
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_file_cmd." ".s:ShellEscape(b:netrw_fname,1)." ".tmpfile)
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_file_cmd." ".netrw#os#Escape(b:netrw_fname,1)." ".tmpfile)
       let result           = s:NetrwGetFile(readcmd, tmpfile, b:netrw_method)
       let b:netrw_lastfile = choice
 
@@ -2359,7 +2359,7 @@
           let uid_machine = g:netrw_machine
         endif
       endif
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(uid_machine.":".b:netrw_fname,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rcp_cmd." ".s:netrw_rcpmode." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(uid_machine.":".b:netrw_fname,1))
       let b:netrw_lastfile = choice
 
       ".........................................
@@ -2385,10 +2385,10 @@
       NetrwKeepj call setline(line("$")+1,'put "'.tmpfile.'" "'.netrw_fname.'"')
       "    call Decho("filter input: ".getline("$"),'~'.expand("<slnum>"))
       if exists("g:netrw_port") && g:netrw_port != ""
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
       else
         "     call Decho("filter input window#".winnr(),'~'.expand("<slnum>"))
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1))
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
       endif
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$"
@@ -2456,7 +2456,7 @@
       " -n  unix : DON'T use <.netrc>, even though it exists
       " -n  win32: quit being obnoxious about password
       NetrwKeepj norm! 1G"_dd
-      call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
+      call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
       " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
       if getline(1) !~ "^$"
         if  !exists("g:netrw_quiet")
@@ -2480,7 +2480,7 @@
       else
         let useport= ""
       endif
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(g:netrw_machine.":".b:netrw_fname,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.useport." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(g:netrw_machine.":".b:netrw_fname,1))
       let b:netrw_lastfile = choice
 
       ".........................................
@@ -2490,7 +2490,7 @@
       let curl= substitute(g:netrw_http_put_cmd,'\s\+.*$',"","")
       if executable(curl)
         let url= g:netrw_choice
-        call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_http_put_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(url,1) )
+        call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_http_put_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(url,1) )
       elseif !exists("g:netrw_quiet")
         call netrw#ErrorMsg(s:ERROR,"can't write to http using <".g:netrw_http_put_cmd.">",16)
       endif
@@ -2522,7 +2522,7 @@
 
       " perform cadaver operation:
       NetrwKeepj norm! 1G"_dd
-      call s:NetrwExe(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
+      call netrw#os#Execute(s:netrw_silentxfer."%!".g:netrw_dav_cmd)
 
       " remove enew buffer (quietly)
       let filtbuf= bufnr("%")
@@ -2536,7 +2536,7 @@
     " NetWrite: (rsync) NetWrite Method #7 {{{3
     elseif     b:netrw_method == 7
       "    call Decho("write via rsync (method #7)",'~'.expand("<slnum>"))
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".s:ShellEscape(tmpfile,1)." ".s:ShellEscape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_rsync_cmd." ".netrw#os#Escape(tmpfile,1)." ".netrw#os#Escape(g:netrw_machine.g:netrw_rsync_sep.b:netrw_fname,1))
       let b:netrw_lastfile = choice
 
       ".........................................
@@ -2560,7 +2560,7 @@
       call setline(1,'put "'.escape(tmpfile,'\').'" '.netrw_fname)
       "    call Decho("filter input: ".getline('.'),'~'.expand("<slnum>"))
       let sftpcmd= substitute(g:netrw_sftp_cmd,"%TEMPFILE%",escape(tmpfile,'\'),"g")
-      call s:NetrwExe(s:netrw_silentxfer."%!".sftpcmd.' '.s:ShellEscape(uid_machine,1))
+      call netrw#os#Execute(s:netrw_silentxfer."%!".sftpcmd.' '.netrw#os#Escape(uid_machine,1))
       let filtbuf= bufnr("%")
       exe curbuf."b!"
       let &l:bh            = bhkeep
@@ -3816,7 +3816,7 @@
       "     "" call Decho("windows+full path: isdirectory(".fname.")",'~'.expand("<slnum>"))
       else
         " windows, relative path given
-        let ret= s:ComposePath(b:netrw_curdir,fname)
+        let ret= netrw#fs#ComposePath(b:netrw_curdir,fname)
         "     "" call Decho("windows+rltv path: isdirectory(".fname.")",'~'.expand("<slnum>"))
       endif
 
@@ -3826,7 +3826,7 @@
     "    "" call Decho("unix+full path: isdirectory(".fname.")",'~'.expand("<slnum>"))
     else
       " not windows, relative path given
-      let ret= s:ComposePath(b:netrw_curdir,fname)
+      let ret= netrw#fs#ComposePath(b:netrw_curdir,fname)
       "    "" call Decho("unix+rltv path: isdirectory(".fname.")",'~'.expand("<slnum>"))
     endif
   else
@@ -3857,21 +3857,21 @@
     if (has("unix") || has("macunix")) && executable("/bin/ls")
 
       if getline(".") == "../"
-        echo system("/bin/ls ".lsopt." ".s:ShellEscape(".."))
-      "     call Decho("#1: echo system(/bin/ls -lsad ".s:ShellEscape(..).")",'~'.expand("<slnum>"))
+        echo system("/bin/ls ".lsopt." ".netrw#os#Escape(".."))
+      "     call Decho("#1: echo system(/bin/ls -lsad ".netrw#os#Escape(..).")",'~'.expand("<slnum>"))
 
       elseif w:netrw_liststyle == s:TREELIST && getline(".") !~ '^'.s:treedepthstring
-        echo system("/bin/ls ".lsopt." ".s:ShellEscape(b:netrw_curdir))
-      "     call Decho("#2: echo system(/bin/ls -lsad ".s:ShellEscape(b:netrw_curdir).")",'~'.expand("<slnum>"))
+        echo system("/bin/ls ".lsopt." ".netrw#os#Escape(b:netrw_curdir))
+      "     call Decho("#2: echo system(/bin/ls -lsad ".netrw#os#Escape(b:netrw_curdir).")",'~'.expand("<slnum>"))
 
       elseif exists("b:netrw_curdir")
-        echo system("/bin/ls ".lsopt." ".s:ShellEscape(s:ComposePath(b:netrw_curdir,a:fname)))
-      "      call Decho("#3: echo system(/bin/ls -lsad ".s:ShellEscape(b:netrw_curdir.a:fname).")",'~'.expand("<slnum>"))
+        echo system("/bin/ls ".lsopt." ".netrw#os#Escape(netrw#fs#ComposePath(b:netrw_curdir,a:fname)))
+      "      call Decho("#3: echo system(/bin/ls -lsad ".netrw#os#Escape(b:netrw_curdir.a:fname).")",'~'.expand("<slnum>"))
 
       else
         "     call Decho('using ls '.a:fname." using cwd<".getcwd().">",'~'.expand("<slnum>"))
-        echo system("/bin/ls ".lsopt." ".s:ShellEscape(s:NetrwFile(a:fname)))
-        "     call Decho("#5: echo system(/bin/ls -lsad ".s:ShellEscape(a:fname).")",'~'.expand("<slnum>"))
+        echo system("/bin/ls ".lsopt." ".netrw#os#Escape(s:NetrwFile(a:fname)))
+        "     call Decho("#5: echo system(/bin/ls -lsad ".netrw#os#Escape(a:fname).")",'~'.expand("<slnum>"))
       endif
     else
       " use vim functions to return information about file below cursor
@@ -3897,21 +3897,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-" s:NetrwFullPath: returns the full path to a directory and/or file {{{2
-fun! s:NetrwFullPath(filename)
-  "  " call Dfunc("s:NetrwFullPath(filename<".a:filename.">)")
-  let filename= a:filename
-  if filename !~ '^/'
-    let filename= resolve(getcwd().'/'.filename)
-  endif
-  if filename != "/" && filename =~ '/$'
-    let filename= substitute(filename,'/$','','')
-  endif
-  "  " call Dret("s:NetrwFullPath <".filename.">")
-  return filename
-endfun
-
-" ---------------------------------------------------------------------
 " s:NetrwGetBuffer: [get a new|find an old netrw] buffer for a netrw listing {{{2
 "   returns 0=cleared buffer
 "           1=re-used buffer (buffer not cleared)
@@ -3935,11 +3920,11 @@
   if exists("w:netrw_liststyle") && w:netrw_liststyle == s:TREELIST
     let bufnum = -1
 
-    if !empty(s:netrwbuf) && has_key(s:netrwbuf,s:NetrwFullPath(dirname))
+    if !empty(s:netrwbuf) && has_key(s:netrwbuf,netrw#fs#AbsPath(dirname))
       if has_key(s:netrwbuf,"NetrwTreeListing")
         let bufnum= s:netrwbuf["NetrwTreeListing"]
       else
-        let bufnum= s:netrwbuf[s:NetrwFullPath(dirname)]
+        let bufnum= s:netrwbuf[netrw#fs#AbsPath(dirname)]
       endif
       "    call Decho("  NetrwTreeListing: bufnum#".bufnum,'~'.expand("<slnum>"))
       if !bufexists(bufnum)
@@ -3954,16 +3939,16 @@
       let bufnum= -1
     endif
 
-  elseif has_key(s:netrwbuf,s:NetrwFullPath(dirname))
-    let bufnum= s:netrwbuf[s:NetrwFullPath(dirname)]
-    "   call Decho("  lookup netrwbuf dictionary: s:netrwbuf[".s:NetrwFullPath(dirname)."]=".bufnum,'~'.expand("<slnum>"))
+  elseif has_key(s:netrwbuf,netrw#fs#AbsPath(dirname))
+    let bufnum= s:netrwbuf[netrw#fs#AbsPath(dirname)]
+    "   call Decho("  lookup netrwbuf dictionary: s:netrwbuf[".netrw#fs#AbsPath(dirname)."]=".bufnum,'~'.expand("<slnum>"))
     if !bufexists(bufnum)
-      call remove(s:netrwbuf,s:NetrwFullPath(dirname))
+      call remove(s:netrwbuf,netrw#fs#AbsPath(dirname))
       let bufnum= -1
     endif
 
   else
-    "   call Decho("  lookup netrwbuf dictionary: s:netrwbuf[".s:NetrwFullPath(dirname)."] not a key",'~'.expand("<slnum>"))
+    "   call Decho("  lookup netrwbuf dictionary: s:netrwbuf[".netrw#fs#AbsPath(dirname)."] not a key",'~'.expand("<slnum>"))
     let bufnum= -1
   endif
   "  call Decho("  bufnum#".bufnum,'~'.expand("<slnum>"))
@@ -4013,8 +3998,8 @@
     else
       call s:NetrwBufRename(dirname)
       " enter the new buffer into the s:netrwbuf dictionary
-      let s:netrwbuf[s:NetrwFullPath(dirname)]= bufnr("%")
-      "    call Decho("update netrwbuf dictionary: s:netrwbuf[".s:NetrwFullPath(dirname)."]=".bufnr("%"),'~'.expand("<slnum>"))
+      let s:netrwbuf[netrw#fs#AbsPath(dirname)]= bufnr("%")
+      "    call Decho("update netrwbuf dictionary: s:netrwbuf[".netrw#fs#AbsPath(dirname)."]=".bufnr("%"),'~'.expand("<slnum>"))
       "    call Decho("netrwbuf dictionary=".string(s:netrwbuf),'~'.expand("<slnum>"))
     endif
   "   call Decho("  named enew buffer#".bufnr("%")."<".bufname("%").">",'~'.expand("<slnum>"))
@@ -4100,23 +4085,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-" s:NetrwGetcwd: get the current directory. {{{2
-"   Change backslashes to forward slashes, if any.
-"   If doesc is true, escape certain troublesome characters
-fun! s:NetrwGetcwd(doesc)
-  "  call Dfunc("NetrwGetcwd(doesc=".a:doesc.")")
-  let curdir= substitute(getcwd(),'\\','/','ge')
-  if curdir !~ '[\/]$'
-    let curdir= curdir.'/'
-  endif
-  if a:doesc
-    let curdir= fnameescape(curdir)
-  endif
-  "  call Dret("NetrwGetcwd <".curdir.">")
-  return curdir
-endfun
-
-" ---------------------------------------------------------------------
 "  s:NetrwGetWord: it gets the directory/file named under the cursor {{{2
 fun! s:NetrwGetWord()
   "  call Dfunc("s:NetrwGetWord() liststyle=".s:ShowStyle()." virtcol=".virtcol("."))
@@ -4556,7 +4524,7 @@
     let dirname= dirname.'/'
   endif
 
-  if newdir !~ dirpat && !(a:islocal && isdirectory(s:NetrwFile(s:ComposePath(dirname,newdir))))
+  if newdir !~ dirpat && !(a:islocal && isdirectory(s:NetrwFile(netrw#fs#ComposePath(dirname,newdir))))
     " ------------------------------
     " NetrwBrowseChgDir: edit a file {{{3
     " ------------------------------
@@ -4573,7 +4541,7 @@
     elseif newdir =~ '^\(/\|\a:\)'
       let dirname= newdir
     else
-      let dirname= s:ComposePath(dirname,newdir)
+      let dirname= netrw#fs#ComposePath(dirname,newdir)
     endif
     " this lets netrw#BrowseX avoid the edit
     if a:0 < 1
@@ -4794,7 +4762,7 @@
     " ----------------------------------------
     " NetrwBrowseChgDir: Go down one directory {{{3
     " ----------------------------------------
-    let dirname    = s:ComposePath(dirname,newdir)
+    let dirname    = netrw#fs#ComposePath(dirname,newdir)
     NetrwKeepj call s:SetRexDir(a:islocal,dirname)
     norm! m`
   endif
@@ -4965,7 +4933,7 @@
     endif
   endif
 
-  call netrw#own#Open(fname)
+  call netrw#os#Open(fname)
 
   " cleanup: remove temporary file,
   "          delete current buffer if success with handler,
@@ -5050,8 +5018,8 @@
   call inputsave()
   let newperm= input("Enter new permission: ")
   call inputrestore()
-  let chgperm= substitute(g:netrw_chgperm,'\<FILENAME\>',s:ShellEscape(expand("<cfile>")),'')
-  let chgperm= substitute(chgperm,'\<PERM\>',s:ShellEscape(newperm),'')
+  let chgperm= substitute(g:netrw_chgperm,'\<FILENAME\>',netrw#os#Escape(expand("<cfile>")),'')
+  let chgperm= substitute(chgperm,'\<PERM\>',netrw#os#Escape(newperm),'')
   call system(chgperm)
   if v:shell_error != 0
     NetrwKeepj call netrw#ErrorMsg(1,"changing permission on file<".expand("<cfile>")."> seems to have failed",75)
@@ -5149,42 +5117,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-" s:NetrwGlob: does glob() if local, remote listing otherwise {{{2
-"     direntry: this is the name of the directory.  Will be fnameescape'd to prevent wildcard handling by glob()
-"     expr    : this is the expression to follow the directory.  Will use s:ComposePath()
-"     pare    =1: remove the current directory from the resulting glob() filelist
-"             =0: leave  the current directory   in the resulting glob() filelist
-fun! s:NetrwGlob(direntry,expr,pare)
-  "  call Dfunc("s:NetrwGlob(direntry<".a:direntry."> expr<".a:expr."> pare=".a:pare.")")
-  if netrw#CheckIfRemote()
-    keepalt 1sp
-    keepalt enew
-    let keep_liststyle    = w:netrw_liststyle
-    let w:netrw_liststyle = s:THINLIST
-    if s:NetrwRemoteListing() == 0
-      keepj keepalt %s@/@@
-      let filelist= getline(1,$)
-      q!
-    else
-      " remote listing error -- leave treedict unchanged
-      let filelist= w:netrw_treedict[a:direntry]
-    endif
-    let w:netrw_liststyle= keep_liststyle
-  else
-    let path= s:ComposePath(fnameescape(a:direntry), a:expr)
-    if has("win32")
-      " escape [ so it is not detected as wildcard character, see :h wildcard
-      let path= substitute(path, '[', '[[]', 'g')
-    endif
-    let filelist = glob(path, 0, 1, 1)
-    if a:pare
-      let filelist= map(filelist,'substitute(v:val, "^.*/", "", "")')
-    endif
-  endif
-  return filelist
-endfun
-
-" ---------------------------------------------------------------------
 " s:NetrwForceFile: (gf support) Force treatment as a file {{{2
 fun! s:NetrwForceFile(islocal,newfile)
   if a:newfile =~ '[/@*=|\\]$'
@@ -5298,13 +5230,24 @@
 "  s:NetrwHome: this function determines a "home" for saving bookmarks and history {{{2
 function! s:NetrwHome()
     if has('nvim')
-        let home = netrw#own#PathJoin(stdpath('state'), 'netrw')
+        let home = netrw#fs#PathJoin(stdpath('state'), 'netrw')
     elseif exists('g:netrw_home')
         let home = expand(g:netrw_home)
     elseif exists('$MYVIMDIR')
         let home = expand('$MYVIMDIR')->substitute('/$', '', '')
     else
-        let home = netrw#own#PathJoin(expand('~'), '.vim')
+        " Pick the first redable directory in 'runtimepath'
+        for path in split(&rtp, ',')
+            if isdirectory(s:NetrwFile(path)) && filewritable(s:NetrwFile(path))
+                let home = path
+                break
+            endif
+        endfor
+
+        if empty(path)
+            " just pick the first directory
+            let home = substitute(&rtp, ',.*$', '', '')
+        endif
     endif
 
     " insure that the home directory exists
@@ -5648,11 +5591,11 @@
         call mkdir(fullnewdir,"p")
       endif
     else
-      let netrw_origdir= s:NetrwGetcwd(1)
+      let netrw_origdir= netrw#fs#Cwd(1)
       if s:NetrwLcd(b:netrw_curdir)
         return
       endif
-      call s:NetrwExe("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.s:ShellEscape(newdirname,1))
+      call netrw#os#Execute("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.netrw#os#Escape(newdirname,1))
       if v:shell_error != 0
         let @@= ykeep
         call netrw#ErrorMsg(s:ERROR,"consider setting g:netrw_localmkdir<".g:netrw_localmkdir."> to something that works",80)
@@ -5678,7 +5621,7 @@
     " Remote mkdir:  using ssh
     let mkdircmd  = s:MakeSshCmd(g:netrw_mkdir_cmd)
     let newdirname= substitute(b:netrw_curdir,'^\%(.\{-}/\)\{3}\(.*\)$','\1','').newdirname
-    call s:NetrwExe("sil! !".mkdircmd." ".s:ShellEscape(newdirname,1))
+    call netrw#os#Execute("sil! !".mkdircmd." ".netrw#os#Escape(newdirname,1))
     if v:shell_error == 0
       " refresh listing
       let svpos= winsaveview()
@@ -6152,10 +6095,10 @@
 
   " handle global markfilelist
   if exists("s:netrwmarkfilelist")
-    let dname= s:ComposePath(b:netrw_curdir,a:fname)
+    let dname= netrw#fs#ComposePath(b:netrw_curdir,a:fname)
     if index(s:netrwmarkfilelist,dname) == -1
       " append new filename to global markfilelist
-      call add(s:netrwmarkfilelist,s:ComposePath(b:netrw_curdir,a:fname))
+      call add(s:netrwmarkfilelist,netrw#fs#ComposePath(b:netrw_curdir,a:fname))
     "    call Decho("append filename<".a:fname."> to global s:markfilelist<".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
     else
       " remove new filename from global markfilelist
@@ -6171,7 +6114,7 @@
   else
     " initialize new global-directory markfilelist
     let s:netrwmarkfilelist= []
-    call add(s:netrwmarkfilelist,s:ComposePath(b:netrw_curdir,a:fname))
+    call add(s:netrwmarkfilelist,netrw#fs#ComposePath(b:netrw_curdir,a:fname))
     "   call Decho("init s:netrwmarkfilelist<".string(s:netrwmarkfilelist).">",'~'.expand("<slnum>"))
   endif
 
@@ -6253,17 +6196,17 @@
       if exists("g:netrw_decompress['".sfx."']")
         " fname has a suffix indicating that its compressed; apply associated decompression routine
         let exe= g:netrw_decompress[sfx]
-        let exe= netrw#WinPath(exe)
+        let exe= netrw#fs#WinPath(exe)
         if a:islocal
           if g:netrw_keepdir
-            let fname= s:ShellEscape(s:ComposePath(curdir,fname))
+            let fname= netrw#os#Escape(netrw#fs#ComposePath(curdir,fname))
           endif
           call system(exe." ".fname)
           if v:shell_error
             NetrwKeepj call netrw#ErrorMsg(s:WARNING,"unable to apply<".exe."> to file<".fname.">",50)
           endif
         else
-          let fname= s:ShellEscape(b:netrw_curdir.fname,1)
+          let fname= netrw#os#Escape(b:netrw_curdir.fname,1)
           NetrwKeepj call s:RemoteSystem(exe." ".fname)
         endif
 
@@ -6274,13 +6217,13 @@
         unlet exe
       elseif a:islocal
         " fname not a compressed file, so compress it
-        call system(netrw#WinPath(g:netrw_compress)." ".s:ShellEscape(s:ComposePath(b:netrw_curdir,fname)))
+        call system(netrw#fs#WinPath(g:netrw_compress)." ".netrw#os#Escape(netrw#fs#ComposePath(b:netrw_curdir,fname)))
         if v:shell_error
           call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_compress<".g:netrw_compress."> to something that works",104)
         endif
       else
         " fname not a compressed file, so compress it
-        NetrwKeepj call s:RemoteSystem(netrw#WinPath(g:netrw_compress)." ".s:ShellEscape(fname))
+        NetrwKeepj call s:RemoteSystem(netrw#fs#WinPath(g:netrw_compress)." ".netrw#os#Escape(fname))
       endif
     endfor       " for every file in the marked list
 
@@ -6338,12 +6281,12 @@
       if len(s:netrwmarkfilelist_{bufnr('%')}) == 1
         " only one marked file
         "     call Decho("case: only one marked file",'~'.expand("<slnum>"))
-        let args    = s:ShellEscape(b:netrw_curdir.s:netrwmarkfilelist_{bufnr('%')}[0])
+        let args    = netrw#os#Escape(b:netrw_curdir.s:netrwmarkfilelist_{bufnr('%')}[0])
         let oldname = s:netrwmarkfilelist_{bufnr('%')}[0]
       elseif a:0 == 1
         "     call Decho("case: handling one input argument",'~'.expand("<slnum>"))
         " this happens when the next case was used to recursively call s:NetrwMarkFileCopy()
-        let args    = s:ShellEscape(b:netrw_curdir.a:1)
+        let args    = netrw#os#Escape(b:netrw_curdir.a:1)
         let oldname = a:1
       else
         " copy multiple marked files inside the same directory
@@ -6368,11 +6311,11 @@
         "     call Dret("s:NetrwMarkFileCopy 0")
         return 0
       endif
-      let args= s:ShellEscape(oldname)
-      let tgt = s:ShellEscape(s:netrwmftgt.'/'.newname)
+      let args= netrw#os#Escape(oldname)
+      let tgt = netrw#os#Escape(s:netrwmftgt.'/'.newname)
     else
-      let args= join(map(deepcopy(s:netrwmarkfilelist_{bufnr('%')}),"s:ShellEscape(b:netrw_curdir.\"/\".v:val)"))
-      let tgt = s:ShellEscape(s:netrwmftgt)
+      let args= join(map(deepcopy(s:netrwmarkfilelist_{bufnr('%')}),"netrw#os#Escape(b:netrw_curdir.\"/\".v:val)"))
+      let tgt = netrw#os#Escape(s:netrwmftgt)
     endif
     if !g:netrw_cygwin && has("win32")
       let args= substitute(args,'/','\\','g')
@@ -6401,9 +6344,9 @@
     if g:netrw_localcopycmd =~ '\s'
       let copycmd     = substitute(copycmd,'\s.*$','','')
       let copycmdargs = substitute(copycmd,'^.\{-}\(\s.*\)$','\1','')
-      let copycmd     = netrw#WinPath(copycmd).copycmdargs
+      let copycmd     = netrw#fs#WinPath(copycmd).copycmdargs
     else
-      let copycmd = netrw#WinPath(copycmd)
+      let copycmd = netrw#fs#WinPath(copycmd)
     endif
     "   call Decho("args   <".args.">",'~'.expand("<slnum>"))
     "   call Decho("tgt    <".tgt.">",'~'.expand("<slnum>"))
@@ -6416,7 +6359,7 @@
       else
         call netrw#ErrorMsg(s:ERROR,"tried using g:netrw_localcopycmd<".g:netrw_localcopycmd.">; it doesn't work!",80)
       endif
-      "    call Dret("s:NetrwMarkFileCopy 0 : failed: system(".g:netrw_localcopycmd." ".args." ".s:ShellEscape(s:netrwmftgt))
+      "    call Dret("s:NetrwMarkFileCopy 0 : failed: system(".g:netrw_localcopycmd." ".args." ".netrw#os#Escape(s:netrwmftgt))
       return 0
     endif
 
@@ -6441,10 +6384,10 @@
     if exists("*mkdir")
       call mkdir(tmpdir)
     else
-      call s:NetrwExe("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.s:ShellEscape(tmpdir,1))
+      call netrw#os#Execute("sil! !".g:netrw_localmkdir.g:netrw_localmkdiropt.' '.netrw#os#Escape(tmpdir,1))
       if v:shell_error != 0
         call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localmkdir<".g:netrw_localmkdir."> to something that works",80)
-        "     call Dret("s:NetrwMarkFileCopy : failed: sil! !".g:netrw_localmkdir.' '.s:ShellEscape(tmpdir,1) )
+        "     call Dret("s:NetrwMarkFileCopy : failed: sil! !".g:netrw_localmkdir.' '.netrw#os#Escape(tmpdir,1) )
         return
       endif
     endif
@@ -6653,10 +6596,10 @@
       for fname in s:netrwmarkfilelist_{curbufnr}
         if a:islocal
           if g:netrw_keepdir
-            let fname= s:ShellEscape(netrw#WinPath(s:ComposePath(curdir,fname)))
+            let fname= netrw#os#Escape(netrw#fs#WinPath(netrw#fs#ComposePath(curdir,fname)))
           endif
         else
-          let fname= s:ShellEscape(netrw#WinPath(b:netrw_curdir.fname))
+          let fname= netrw#os#Escape(netrw#fs#WinPath(b:netrw_curdir.fname))
         endif
         if cmd =~ '%'
           let xcmd= substitute(cmd,'%',fname,'g')
@@ -6701,9 +6644,9 @@
       return
     endif
     if cmd =~ '%'
-      let cmd= substitute(cmd,'%',join(map(s:netrwmarkfilelist,'s:ShellEscape(v:val)'),' '),'g')
+      let cmd= substitute(cmd,'%',join(map(s:netrwmarkfilelist,'netrw#os#Escape(v:val)'),' '),'g')
     else
-      let cmd= cmd.' '.join(map(s:netrwmarkfilelist,'s:ShellEscape(v:val)'),' ')
+      let cmd= cmd.' '.join(map(s:netrwmarkfilelist,'netrw#os#Escape(v:val)'),' ')
     endif
     if a:islocal
       call system(cmd)
@@ -6970,7 +6913,7 @@
       "    call Dfunc("s:NetrwMarkFileMove : g:netrw_localmovecmd<".g:netrw_localmovecmd."> n/a!")
       return
     endif
-    let tgt = s:ShellEscape(s:netrwmftgt)
+    let tgt = netrw#os#Escape(s:netrwmftgt)
     "   call Decho("tgt<".tgt.">",'~'.expand("<slnum>"))
     if !g:netrw_cygwin && has("win32")
       let tgt= substitute(tgt, '/','\\','g')
@@ -6978,14 +6921,14 @@
       if g:netrw_localmovecmd =~ '\s'
         let movecmd     = substitute(g:netrw_localmovecmd,'\s.*$','','')
         let movecmdargs = substitute(g:netrw_localmovecmd,'^.\{-}\(\s.*\)$','\1','')
-        let movecmd     = netrw#WinPath(movecmd).movecmdargs
+        let movecmd     = netrw#fs#WinPath(movecmd).movecmdargs
       "     call Decho("windows exception: movecmd<".movecmd."> (#1: had a space)",'~'.expand("<slnum>"))
       else
-        let movecmd = netrw#WinPath(g:netrw_localmovecmd)
+        let movecmd = netrw#fs#WinPath(g:netrw_localmovecmd)
         "     call Decho("windows exception: movecmd<".movecmd."> (#2: no space)",'~'.expand("<slnum>"))
       endif
     else
-      let movecmd = netrw#WinPath(g:netrw_localmovecmd)
+      let movecmd = netrw#fs#WinPath(g:netrw_localmovecmd)
       "    call Decho("movecmd<".movecmd."> (#3 linux or cygwin)",'~'.expand("<slnum>"))
     endif
     for fname in s:netrwmarkfilelist_{bufnr("%")}
@@ -6996,8 +6939,8 @@
       if !g:netrw_cygwin && has("win32")
         let fname= substitute(fname,'/','\\','g')
       endif
-      "    call Decho("system(".movecmd." ".s:ShellEscape(fname)." ".tgt.")",'~'.expand("<slnum>"))
-      let ret= system(movecmd.g:netrw_localmovecmdopt." ".s:ShellEscape(fname)." ".tgt)
+      "    call Decho("system(".movecmd." ".netrw#os#Escape(fname)." ".tgt.")",'~'.expand("<slnum>"))
+      let ret= system(movecmd.g:netrw_localmovecmdopt." ".netrw#os#Escape(fname)." ".tgt)
       if v:shell_error != 0
         if exists("b:netrw_curdir") && b:netrw_curdir != getcwd() && !g:netrw_keepdir
           call netrw#ErrorMsg(s:ERROR,"move failed; perhaps due to vim's current directory<".getcwd()."> not matching netrw's (".b:netrw_curdir.") (see :help netrw-cd)",100)
@@ -7095,7 +7038,7 @@
     for fname in netrwmarkfilelist
       if a:islocal
         if g:netrw_keepdir
-          let fname= s:ComposePath(curdir,fname)
+          let fname= netrw#fs#ComposePath(curdir,fname)
         endif
       else
         let fname= curdir.fname
@@ -7131,7 +7074,7 @@
     " get the matching list of files using local glob()
     "   call Decho("handle local regexp",'~'.expand("<slnum>"))
     let dirname = escape(b:netrw_curdir,g:netrw_glob_escape)
-    let filelist= glob(s:ComposePath(dirname,regexp),0,1,1)
+    let filelist= glob(netrw#fs#ComposePath(dirname,regexp),0,1,1)
     "   call Decho("files<".string(filelist).">",'~'.expand("<slnum>"))
 
     " mark the list of files
@@ -7215,7 +7158,7 @@
     for fname in netrwmarkfilelist
       if a:islocal
         if g:netrw_keepdir
-          let fname= s:ComposePath(curdir,fname)
+          let fname= netrw#fs#ComposePath(curdir,fname)
         endif
       else
         let fname= curdir.fname
@@ -7244,7 +7187,7 @@
   endif
 
   if exists("s:netrwmarkfilelist")
-    let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "s:ShellEscape(v:val,".!a:islocal.")"))
+    let netrwmarkfilelist= join(map(deepcopy(s:netrwmarkfilelist), "netrw#os#Escape(v:val,".!a:islocal.")"))
     call s:NetrwUnmarkAll()
 
     if a:islocal
@@ -7305,7 +7248,7 @@
     "  * If directory, use it for the target.
     "  * If file, use b:netrw_curdir for the target
     let curword= s:NetrwGetWord()
-    let tgtdir = s:ComposePath(curdir,curword)
+    let tgtdir = netrw#fs#ComposePath(curdir,curword)
     if a:islocal && isdirectory(s:NetrwFile(tgtdir))
       let s:netrwmftgt = tgtdir
     elseif !a:islocal && tgtdir =~ '/$'
@@ -7319,7 +7262,7 @@
     let s:netrwmftgt= simplify(s:netrwmftgt)
   endif
   if g:netrw_cygwin
-    let s:netrwmftgt= substitute(system("cygpath ".s:ShellEscape(s:netrwmftgt)),'\n$','','')
+    let s:netrwmftgt= substitute(system("cygpath ".netrw#os#Escape(s:netrwmftgt)),'\n$','','')
     let s:netrwmftgt= substitute(s:netrwmftgt,'\n$','','')
   endif
   let s:netrwmftgt_islocal= a:islocal
@@ -7495,7 +7438,7 @@
   "  remove all files in local marked-file list from global list
   if exists("s:netrwmarkfilelist")
     for mfile in s:netrwmarkfilelist_{a:curbufnr}
-      let dfile = s:ComposePath(a:curdir,mfile)       " prepend directory to mfile
+      let dfile = netrw#fs#ComposePath(a:curdir,mfile)       " prepend directory to mfile
       let idx   = index(s:netrwmarkfilelist,dfile)    " get index in list of dfile
       call remove(s:netrwmarkfilelist,idx)            " remove from global list
     endfor
@@ -7866,7 +7809,7 @@
         return
       endif
       let filelist= deepcopy(s:netrwmarkfilelist_{bufnr('%')})
-      let args    = join(map(filelist,"s:ShellEscape(v:val, 1)"))
+      let args    = join(map(filelist,"netrw#os#Escape(v:val, 1)"))
       if exists("g:netrw_port") && g:netrw_port != ""
         let useport= " ".g:netrw_scpport." ".g:netrw_port
       else
@@ -7874,7 +7817,7 @@
       endif
       let machine = substitute(a:tgt,'^scp://\([^/:]\+\).*$','\1','')
       let tgt     = substitute(a:tgt,'^scp://[^/]\+/\(.*\)$','\1','')
-      call s:NetrwExe(s:netrw_silentxfer."!".g:netrw_scp_cmd.s:ShellEscape(useport,1)." ".args." ".s:ShellEscape(machine.":".tgt,1))
+      call netrw#os#Execute(s:netrw_silentxfer."!".g:netrw_scp_cmd.netrw#os#Escape(useport,1)." ".args." ".netrw#os#Escape(machine.":".tgt,1))
       if s:NetrwLcd(curdir)
         "     call Dret("s:NetrwUpload : lcd failure")
         return
@@ -7912,10 +7855,10 @@
         endfor
 
         if exists("g:netrw_port") && g:netrw_port != ""
-          call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1))
+          call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1))
         else
           "      call Decho("filter input window#".winnr(),'~'.expand("<slnum>"))
-          call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1))
+          call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1))
         endif
         " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
         sil NetrwKeepj g/Local directory now/d
@@ -7978,7 +7921,7 @@
         " -n  unix : DON'T use <.netrc>, even though it exists
         " -n  win32: quit being obnoxious about password
         NetrwKeepj norm! 1G"_dd
-        call s:NetrwExe(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
+        call netrw#os#Execute(s:netrw_silentxfer."%!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
         " If the result of the ftp operation isn't blank, show an error message (tnx to Doug Claar)
         sil NetrwKeepj g/Local directory now/d
         call histdel("/",-1)
@@ -8602,8 +8545,8 @@
 
     elseif entry =~ '@$' && has_key(w:netrw_treedict,direntry.'@')
       NetrwKeepj call s:NetrwRefreshTreeDict(direntry.'/')
-      let liststar   = s:NetrwGlob(direntry.'/','*',1)
-      let listdotstar= s:NetrwGlob(direntry.'/','.*',1)
+      let liststar   = netrw#fs#Glob(direntry.'/','*',1)
+      let listdotstar= netrw#fs#Glob(direntry.'/','.*',1)
 
     else
     endif
@@ -9208,11 +9151,11 @@
     NetrwKeepj call setline(line("$")+1,a:listcmd)
     "   exe "NetrwKeepj ".w:netrw_bannercnt.',$g/^./call Decho("ftp#".line(".").": ".getline("."),''~''.expand("<slnum>"))'
     if exists("g:netrw_port") && g:netrw_port != ""
-      "    call Decho("exe ".s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1),'~'.expand("<slnum>"))
-      exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)." ".s:ShellEscape(g:netrw_port,1)
+      "    call Decho("exe ".s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1),'~'.expand("<slnum>"))
+      exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)." ".netrw#os#Escape(g:netrw_port,1)
     else
-      "    call Decho("exe ".s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1),'~'.expand("<slnum>"))
-      exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".s:ShellEscape(g:netrw_machine,1)
+      "    call Decho("exe ".s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1),'~'.expand("<slnum>"))
+      exe s:netrw_silentxfer." NetrwKeepj ".w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." -i ".netrw#os#Escape(g:netrw_machine,1)
     endif
 
     ".........................................
@@ -9257,7 +9200,7 @@
     " -n  win32: quit being obnoxious about password
     if exists("w:netrw_bannercnt")
       "    exe w:netrw_bannercnt.',$g/^./call Decho("ftp#".line(".").": ".getline("."),''~''.expand("<slnum>"))'
-      call s:NetrwExe(s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
+      call netrw#os#Execute(s:netrw_silentxfer.w:netrw_bannercnt.",$!".s:netrw_ftp_cmd." ".g:netrw_ftp_options)
       "   else " Decho
       "    call Decho("WARNING: w:netrw_bannercnt doesn't exist!",'~'.expand("<slnum>"))
       "    g/^./call Decho("SKIPPING ftp#".line(".").": ".getline("."),'~'.expand("<slnum>"))
@@ -9434,8 +9377,8 @@
     let listcmd= s:MakeSshCmd(g:netrw_list_cmd)
     "   call Decho("listcmd<".listcmd."> (using g:netrw_list_cmd)",'~'.expand("<slnum>"))
     if g:netrw_scp_cmd =~ '^pscp'
-      "    call Decho("1: exe r! ".s:ShellEscape(listcmd.s:path, 1),'~'.expand("<slnum>"))
-      exe "NetrwKeepj r! ".listcmd.s:ShellEscape(s:path, 1)
+      "    call Decho("1: exe r! ".netrw#os#Escape(listcmd.s:path, 1),'~'.expand("<slnum>"))
+      exe "NetrwKeepj r! ".listcmd.netrw#os#Escape(s:path, 1)
       " remove rubbish and adjust listing format of 'pscp' to 'ssh ls -FLa' like
       sil! NetrwKeepj g/^Listing directory/NetrwKeepj d
       sil! NetrwKeepj g/^d[-rwx][-rwx][-rwx]/NetrwKeepj s+$+/+e
@@ -9452,8 +9395,8 @@
         "     call Decho("2: exe r! ".listcmd,'~'.expand("<slnum>"))
         exe "NetrwKeepj keepalt r! ".listcmd
       else
-        "     call Decho("3: exe r! ".listcmd.' '.s:ShellEscape(fnameescape(s:path),1),'~'.expand("<slnum>"))
-        exe "NetrwKeepj keepalt r! ".listcmd.' '.s:ShellEscape(fnameescape(s:path),1)
+        "     call Decho("3: exe r! ".listcmd.' '.netrw#os#Escape(fnameescape(s:path),1),'~'.expand("<slnum>"))
+        exe "NetrwKeepj keepalt r! ".listcmd.' '.netrw#os#Escape(fnameescape(s:path),1)
         "     call Decho("listcmd<".listcmd."> path<".s:path.">",'~'.expand("<slnum>"))
       endif
     endif
@@ -9607,9 +9550,9 @@
           "      call Decho("remotedir<".remotedir.">",'~'.expand("<slnum>"))
           "      call Decho("rmfile<".a:rmfile.">",'~'.expand("<slnum>"))
           if remotedir != ""
-            let netrw_rm_cmd= netrw_rm_cmd." ".s:ShellEscape(fnameescape(remotedir.a:rmfile))
+            let netrw_rm_cmd= netrw_rm_cmd." ".netrw#os#Escape(fnameescape(remotedir.a:rmfile))
           else
-            let netrw_rm_cmd= netrw_rm_cmd." ".s:ShellEscape(fnameescape(a:rmfile))
+            let netrw_rm_cmd= netrw_rm_cmd." ".netrw#os#Escape(fnameescape(a:rmfile))
           endif
           "      call Decho("call system(".netrw_rm_cmd.")",'~'.expand("<slnum>"))
           let ret= system(netrw_rm_cmd)
@@ -9650,14 +9593,14 @@
         NetrwKeepj call s:NetrwRemoteFtpCmd(a:path,"rmdir ".a:rmfile)
       else
         let rmfile          = substitute(a:path.a:rmfile,'/$','','')
-        let netrw_rmdir_cmd = s:MakeSshCmd(netrw#WinPath(g:netrw_rmdir_cmd)).' '.s:ShellEscape(netrw#WinPath(rmfile))
+        let netrw_rmdir_cmd = s:MakeSshCmd(netrw#fs#WinPath(g:netrw_rmdir_cmd)).' '.netrw#os#Escape(netrw#fs#WinPath(rmfile))
         "      call Decho("attempt to remove dir: system(".netrw_rmdir_cmd.")",'~'.expand("<slnum>"))
         let ret= system(netrw_rmdir_cmd)
         "      call Decho("returned=".ret." errcode=".v:shell_error,'~'.expand("<slnum>"))
 
         if v:shell_error != 0
           "      call Decho("v:shell_error not 0",'~'.expand("<slnum>"))
-          let netrw_rmf_cmd= s:MakeSshCmd(netrw#WinPath(g:netrw_rmf_cmd)).' '.s:ShellEscape(netrw#WinPath(substitute(rmfile,'[\/]$','','e')))
+          let netrw_rmf_cmd= s:MakeSshCmd(netrw#fs#WinPath(g:netrw_rmf_cmd)).' '.netrw#os#Escape(netrw#fs#WinPath(substitute(rmfile,'[\/]$','','e')))
           "      call Decho("2nd attempt to remove dir: system(".netrw_rmf_cmd.")",'~'.expand("<slnum>"))
           let ret= system(netrw_rmf_cmd)
           "      call Decho("returned=".ret." errcode=".v:shell_error,'~'.expand("<slnum>"))
@@ -9706,9 +9649,9 @@
       if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
         NetrwKeepj call s:NetrwRemoteFtpCmd(a:path,"rename ".oldname." ".newname)
       else
-        let oldname= s:ShellEscape(a:path.oldname)
-        let newname= s:ShellEscape(a:path.newname)
-        let ret    = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname)
+        let oldname= netrw#os#Escape(a:path.oldname)
+        let newname= netrw#os#Escape(a:path.newname)
+        let ret    = system(netrw#fs#WinPath(rename_cmd).' '.oldname.' '.newname)
       endif
 
     endfor
@@ -9731,9 +9674,9 @@
       if exists("w:netrw_method") && (w:netrw_method == 2 || w:netrw_method == 3)
         call s:NetrwRemoteFtpCmd(a:path,"rename ".oldname." ".newname)
       else
-        let oldname= s:ShellEscape(a:path.oldname)
-        let newname= s:ShellEscape(a:path.newname)
-        let ret    = system(netrw#WinPath(rename_cmd).' '.oldname.' '.newname)
+        let oldname= netrw#os#Escape(a:path.oldname)
+        let newname= netrw#os#Escape(a:path.newname)
+        let ret    = system(netrw#fs#WinPath(rename_cmd).' '.oldname.' '.newname)
       endif
 
       let ctr= ctr + 1
@@ -9988,13 +9931,13 @@
   " get the list of files contained in the current directory
   let dirname    = a:dirname
   let dirnamelen = strlen(dirname)
-  let filelist   = s:NetrwGlob(dirname,"*",0)
-  let filelist   = filelist + s:NetrwGlob(dirname,".*",0)
+  let filelist   = netrw#fs#Glob(dirname,"*",0)
+  let filelist   = filelist + netrw#fs#Glob(dirname,".*",0)
 
   if g:netrw_cygwin == 0 && has("win32")
   elseif index(filelist,'..') == -1 && dirname !~ '/'
     " include ../ in the glob() entry if its missing
-    let filelist= filelist+[s:ComposePath(dirname,"../")]
+    let filelist= filelist+[netrw#fs#ComposePath(dirname,"../")]
   endif
 
   if a:setmaxfilenamelen && get(g:, 'netrw_dynamic_maxfilenamelen', 0)
@@ -10202,7 +10145,7 @@
       endif
 
       NetrwKeepj norm! 0
-      let oldname= s:ComposePath(a:path,curword)
+      let oldname= netrw#fs#ComposePath(a:path,curword)
 
       call inputsave()
       let newname= input("Moving ".oldname." to : ",substitute(oldname,'/*$','','e'))
@@ -10295,7 +10238,7 @@
     let ok = ""
     let dir = 0
     NetrwKeepj norm! 0
-    let rmfile = s:NetrwFile(s:ComposePath(a:path, escape(a:fname, '\\')))->fnamemodify(':.')
+    let rmfile = s:NetrwFile(netrw#fs#ComposePath(a:path, escape(a:fname, '\\')))->fnamemodify(':.')
 
     " if not a directory
     if rmfile !~ '^"' && (rmfile =~ '@$' || rmfile !~ '[\/]$')
@@ -10490,65 +10433,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-"  s:ComposePath: Appends a new part to a path taking different systems into consideration {{{2
-fun! s:ComposePath(base,subdir)
-  "  call Dfunc("s:ComposePath(base<".a:base."> subdir<".a:subdir.">)")
-
-  if has("amiga")
-    "   call Decho("amiga",'~'.expand("<slnum>"))
-    let ec = a:base[s:Strlen(a:base)-1]
-    if ec != '/' && ec != ':'
-      let ret = a:base."/" . a:subdir
-    else
-      let ret = a:base.a:subdir
-    endif
-
-  " COMBAK: test on windows with changing to root directory: :e C:/
-  elseif a:subdir =~ '^\a:[/\\]\([^/\\]\|$\)' && has("win32")
-    "   call Decho("windows",'~'.expand("<slnum>"))
-    let ret= a:subdir
-
-  elseif a:base =~ '^\a:[/\\]\([^/\\]\|$\)' && has("win32")
-    "   call Decho("windows",'~'.expand("<slnum>"))
-    if a:base =~ '[/\\]$'
-      let ret= a:base.a:subdir
-    else
-      let ret= a:base.'/'.a:subdir
-    endif
-
-  elseif a:base =~ '^\a\{3,}://'
-    "   call Decho("remote linux/macos",'~'.expand("<slnum>"))
-    let urlbase = substitute(a:base,'^\(\a\+://.\{-}/\)\(.*\)$','\1','')
-    let curpath = substitute(a:base,'^\(\a\+://.\{-}/\)\(.*\)$','\2','')
-    if a:subdir == '../'
-      if curpath =~ '[^/]/[^/]\+/$'
-        let curpath= substitute(curpath,'[^/]\+/$','','')
-      else
-        let curpath=""
-      endif
-      let ret= urlbase.curpath
-    else
-      let ret= urlbase.curpath.a:subdir
-    endif
-  "   call Decho("urlbase<".urlbase.">",'~'.expand("<slnum>"))
-  "   call Decho("curpath<".curpath.">",'~'.expand("<slnum>"))
-  "   call Decho("ret<".ret.">",'~'.expand("<slnum>"))
-
-  else
-    "   call Decho("local linux/macos",'~'.expand("<slnum>"))
-    let ret = substitute(a:base."/".a:subdir,"//","/","g")
-    if a:base =~ '^//'
-      " keeping initial '//' for the benefit of network share listing support
-      let ret= '/'.ret
-    endif
-    let ret= simplify(ret)
-  endif
-
-  "  call Dret("s:ComposePath ".ret)
-  return ret
-endfun
-
-" ---------------------------------------------------------------------
 " s:DeleteBookmark: deletes a file/directory from Netrw's bookmark system {{{2
 "   Related Functions: s:MakeBookmark() s:NetrwBookHistHandler() s:NetrwBookmark()
 fun! s:DeleteBookmark(fname)
@@ -10843,7 +10727,7 @@
 "           acceptable.  No effect on Unix paths.
 "  Examples of use:  let result= s:NetrwDelete(path)
 function! s:NetrwDelete(path)
-    let path = netrw#WinPath(a:path)
+    let path = netrw#fs#WinPath(a:path)
 
     if !g:netrw_cygwin && has("win32") && exists("+shellslash")
         let sskeep = &shellslash
@@ -10966,26 +10850,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-" s:NetrwExe: executes a string using "!" {{{2
-fun! s:NetrwExe(cmd)
-  if has("win32") && exepath(&shell) !~? '\v[\/]?(cmd|pwsh|powershell)(\.exe)?$' && !g:netrw_cygwin
-    let savedShell=[&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash]
-    set shell& shellcmdflag& shellxquote& shellxescape&
-    set shellquote& shellpipe& shellredir& shellslash&
-    try
-      exe a:cmd
-    finally
-      let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell
-    endtry
-  else
-    exe a:cmd
-  endif
-  if v:shell_error
-    call netrw#ErrorMsg(s:WARNING,"shell signalled an error",106)
-  endif
-endfun
-
-" ---------------------------------------------------------------------
 " s:NetrwInsureWinVars: insure that a netrw buffer has its w: variables in spite of a wincmd v or s {{{2
 fun! s:NetrwInsureWinVars()
   if !exists("w:netrw_liststyle")
@@ -11172,7 +11036,7 @@
 "                 Returns status
 " Runs system() on
 "    [cd REMOTEDIRPATH;] a:cmd
-" Note that it doesn't do s:ShellEscape(a:cmd)!
+" Note that it doesn't do netrw#os#Escape(a:cmd)!
 fun! s:RemoteSystem(cmd)
   "  call Dfunc("s:RemoteSystem(cmd<".a:cmd.">)")
   if !executable(g:netrw_ssh_cmd)
@@ -11183,7 +11047,7 @@
     let cmd      = s:MakeSshCmd(g:netrw_ssh_cmd." USEPORT HOSTNAME")
     let remotedir= substitute(b:netrw_curdir,'^.*//[^/]\+/\(.*\)$','\1','')
     if remotedir != ""
-      let cmd= cmd.' cd '.s:ShellEscape(remotedir).";"
+      let cmd= cmd.' cd '.netrw#os#Escape(remotedir).";"
     else
       let cmd= cmd.' '
     endif
@@ -11497,15 +11361,6 @@
 endfun
 
 " ---------------------------------------------------------------------
-" s:ShellEscape: shellescape(), or special windows handling {{{2
-fun! s:ShellEscape(s, ...)
-  if has('win32') && $SHELL == '' && &shellslash
-    return printf('"%s"', substitute(a:s, '"', '""', 'g'))
-  endif
-  let f = a:0 > 0 ? a:1 : 0
-  return shellescape(a:s, f)
-endfun
-
 " ---------------------------------------------------------------------
 " s:TreeListMove: supports [[, ]], [], and ][ in tree mode {{{2
 fun! s:TreeListMove(dir)
@@ -11616,15 +11471,20 @@
 " Deprecated: {{{1
 
 function! netrw#Launch(args)
-    call netrw#own#Deprecate('netrw#Launch', 'v180', {'vim': 'dist#vim9#Launch', 'nvim': 'vim.system'})
+    call netrw#msg#Deprecate('netrw#Launch', 'v180', {'vim': 'dist#vim9#Launch', 'nvim': 'vim.system'})
     if !has('nvim')
         call dist#vim9#Launch(args)
     endif
 endfunction
 
 function! netrw#Open(file)
-    call netrw#own#Deprecate('netrw#Open', 'v180', {'vim': 'dist#vim9#Open', 'nvim': 'vim.ui.open'})
-    call netrw#own#Open(a:file)
+    call netrw#msg#Deprecate('netrw#Open', 'v180', {'vim': 'dist#vim9#Open', 'nvim': 'vim.ui.open'})
+    call netrw#os#Open(a:file)
+endfunction
+
+function! netrw#WinPath(path)
+    call netrw#msg#Deprecate('netrw#WinPath', 'v180', {})
+    call netrw#fs#WinPath(a:path)
 endfunction
 
 " }}}
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw/fs.vim b/runtime/pack/dist/opt/netrw/autoload/netrw/fs.vim
new file mode 100644
index 0000000..091fea2
--- /dev/null
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw/fs.vim
@@ -0,0 +1,167 @@
+" FUNCTIONS IN THIS FILE ARE MEANT TO BE USED BY NETRW.VIM AND NETRW.VIM ONLY.
+" THESE FUNCTIONS DON'T COMMIT TO ANY BACKWARDS COMPATIBILITY. SO CHANGES AND
+" BREAKAGES IF USED OUTSIDE OF NETRW.VIM ARE EXPECTED.
+
+let s:slash = &shellslash ? '/' : '\'
+
+" netrw#fs#PathJoin: Appends a new part to a path taking different systems into consideration {{{
+
+function! netrw#fs#PathJoin(...)
+    let path = ""
+
+    for arg in a:000
+        if empty(path)
+            let path = arg
+        else
+            let path .= s:slash . arg
+        endif
+    endfor
+
+    return path
+endfunction
+
+" }}}
+" netrw#fs#ComposePath: Appends a new part to a path taking different systems into consideration {{{
+
+function! netrw#fs#ComposePath(base, subdir)
+    if has('amiga')
+        let ec = a:base[s:Strlen(a:base)-1]
+        if ec != '/' && ec != ':'
+            let ret = a:base . '/' . a:subdir
+        else
+            let ret = a:base.a:subdir
+        endif
+
+        " COMBAK: test on windows with changing to root directory: :e C:/
+    elseif a:subdir =~ '^\a:[/\\]\([^/\\]\|$\)' && has('win32')
+        let ret = a:subdir
+
+    elseif a:base =~ '^\a:[/\\]\([^/\\]\|$\)' && has('win32')
+        if a:base =~ '[/\\]$'
+            let ret = a:base . a:subdir
+        else
+            let ret = a:base . '/' . a:subdir
+        endif
+
+    elseif a:base =~ '^\a\{3,}://'
+        let urlbase = substitute(a:base, '^\(\a\+://.\{-}/\)\(.*\)$', '\1', '')
+        let curpath = substitute(a:base, '^\(\a\+://.\{-}/\)\(.*\)$', '\2', '')
+        if a:subdir == '../'
+            if curpath =~ '[^/]/[^/]\+/$'
+                let curpath = substitute(curpath, '[^/]\+/$', '', '')
+            else
+                let curpath = ''
+            endif
+            let ret = urlbase.curpath
+        else
+            let ret = urlbase.curpath.a:subdir
+        endif
+
+    else
+        let ret = substitute(a:base . '/' .a:subdir, '//', '/', 'g')
+        if a:base =~ '^//'
+            " keeping initial '//' for the benefit of network share listing support
+            let ret = '/' . ret
+        endif
+        let ret = simplify(ret)
+    endif
+
+    return ret
+endfunction
+
+" }}}
+" netrw#fs#AbsPath: returns the full path to a directory and/or file {{{
+
+function! netrw#fs#AbsPath(filename)
+    let filename = a:filename
+
+    if filename !~ '^/'
+        let filename = resolve(getcwd() . '/' . filename)
+    endif
+
+    if filename != "/" && filename =~ '/$'
+        let filename = substitute(filename, '/$', '', '')
+    endif
+
+    return filename
+endfunction
+
+" }}}
+" netrw#fs#Cwd: get the current directory. {{{
+"   Change backslashes to forward slashes, if any.
+"   If doesc is true, escape certain troublesome characters
+
+function! netrw#fs#Cwd(doesc)
+    let curdir = substitute(getcwd(), '\\', '/', 'ge')
+
+    if curdir !~ '[\/]$'
+        let curdir .= '/'
+    endif
+
+    if a:doesc
+        let curdir = fnameescape(curdir)
+    endif
+
+    return curdir
+endfunction
+
+" }}}
+" netrw#fs#Glob: does glob() if local, remote listing otherwise {{{
+"     direntry: this is the name of the directory.  Will be fnameescape'd to prevent wildcard handling by glob()
+"     expr    : this is the expression to follow the directory.  Will use netrw#fs#ComposePath()
+"     pare    =1: remove the current directory from the resulting glob() filelist
+"             =0: leave  the current directory   in the resulting glob() filelist
+
+function! netrw#fs#Glob(direntry, expr, pare)
+    if netrw#CheckIfRemote()
+        keepalt 1sp
+        keepalt enew
+        let keep_liststyle = w:netrw_liststyle
+        let w:netrw_liststyle = s:THINLIST
+        if s:NetrwRemoteListing() == 0
+            keepj keepalt %s@/@@
+            let filelist = getline(1,$)
+            q!
+        else
+            " remote listing error -- leave treedict unchanged
+            let filelist = w:netrw_treedict[a:direntry]
+        endif
+        let w:netrw_liststyle = keep_liststyle
+    else
+        let path= netrw#fs#ComposePath(fnameescape(a:direntry), a:expr)
+        if has("win32")
+            " escape [ so it is not detected as wildcard character, see :h wildcard
+            let path = substitute(path, '[', '[[]', 'g')
+        endif
+        let filelist = glob(path, 0, 1, 1)
+        if a:pare
+            let filelist = map(filelist,'substitute(v:val, "^.*/", "", "")')
+        endif
+    endif
+
+    return filelist
+endfunction
+
+" }}}
+" netrw#fs#WinPath: tries to insure that the path is windows-acceptable, whether cygwin is used or not {{{
+
+function! netrw#fs#WinPath(path)
+    if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && has("win32")
+        " remove cygdrive prefix, if present
+        let path = substitute(a:path, g:netrw_cygdrive . '/\(.\)', '\1:', '')
+        " remove trailing slash (Win95)
+        let path = substitute(path, '\(\\\|/\)$', '', 'g')
+        " remove escaped spaces
+        let path = substitute(path, '\ ', ' ', 'g')
+        " convert slashes to backslashes
+        let path = substitute(path, '/', '\', 'g')
+    else
+        let path = a:path
+    endif
+
+    return path
+endfunction
+
+" }}}
+
+" vim:ts=8 sts=4 sw=4 et fdm=marker
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw/msg.vim b/runtime/pack/dist/opt/netrw/autoload/netrw/msg.vim
new file mode 100644
index 0000000..bf5fadb
--- /dev/null
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw/msg.vim
@@ -0,0 +1,30 @@
+" FUNCTIONS IN THIS FILE ARE MEANT TO BE USED BY NETRW.VIM AND NETRW.VIM ONLY.
+" THESE FUNCTIONS DON'T COMMIT TO ANY BACKWARDS COMPATIBILITY. SO CHANGES AND
+" BREAKAGES IF USED OUTSIDE OF NETRW.VIM ARE EXPECTED.
+
+let s:deprecation_msgs = []
+function! netrw#own#Deprecate(name, version, alternatives)
+    " If running on neovim use vim.deprecate
+    if has('nvim')
+        let s:alternative = a:alternatives->get('nvim', v:null)
+        call v:lua.vim.deprecate(a:name, s:alternative, a:version, "netrw", v:false)
+        return
+    endif
+
+    " If we did notify for something only do it once
+    if s:deprecation_msgs->index(a:name) >= 0
+        return
+    endif
+
+    let s:alternative = a:alternatives->get('vim', v:null)
+    echohl WarningMsg
+    echomsg s:alternative != v:null
+                \ ? printf('%s is deprecated, use %s instead.', a:name, s:alternative)
+                \ : printf('%s is deprecated.', a:name)
+    echomsg printf('Feature will be removed in netrw %s', a:version)
+    echohl None
+
+    call add(s:deprecation_msgs, a:name)
+endfunction
+
+" vim:ts=8 sts=4 sw=4 et fdm=marker
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw/os.vim b/runtime/pack/dist/opt/netrw/autoload/netrw/os.vim
new file mode 100644
index 0000000..6095d0d
--- /dev/null
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw/os.vim
@@ -0,0 +1,48 @@
+" FUNCTIONS IN THIS FILE ARE MEANT TO BE USED BY NETRW.VIM AND NETRW.VIM ONLY.
+" THESE FUNCTIONS DON'T COMMIT TO ANY BACKWARDS COMPATIBILITY. SO CHANGES AND
+" BREAKAGES IF USED OUTSIDE OF NETRW.VIM ARE EXPECTED.
+
+" netrw#os#Execute: executes a string using "!" {{{
+
+function! netrw#os#Execute(cmd)
+    if has("win32") && exepath(&shell) !~? '\v[\/]?(cmd|pwsh|powershell)(\.exe)?$' && !g:netrw_cygwin
+        let savedShell=[&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash]
+        set shell& shellcmdflag& shellxquote& shellxescape&
+        set shellquote& shellpipe& shellredir& shellslash&
+        try
+            execute a:cmd
+        finally
+            let [&shell,&shellcmdflag,&shellxquote,&shellxescape,&shellquote,&shellpipe,&shellredir,&shellslash] = savedShell
+        endtry
+    else
+        execute a:cmd
+    endif
+
+    if v:shell_error
+        call netrw#ErrorMsg(s:WARNING, "shell signalled an error", 106)
+    endif
+endfunction
+
+" }}}
+" netrw#os#Escape: shellescape(), or special windows handling {{{
+
+function! netrw#os#Escape(string, ...)
+    return has('win32') && empty($SHELL) && &shellslash
+        \ ? printf('"%s"', substitute(a:string, '"', '""', 'g'))
+        \ : shellescape(a:string, a:0 > 0 ? a:1 : 0)
+endfunction
+
+" }}}
+" netrw#os#Open: open file with os viewer (eg. xdg-open) {{{
+
+function! netrw#os#Open(file) abort
+    if has('nvim')
+        call luaeval('vim.ui.open(_A[1]) and nil', [a:file])
+    else
+        call dist#vim9#Open(a:file)
+    endif
+endfunction
+
+" }}}
+
+" vim:ts=8 sts=4 sw=4 et fdm=marker
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw/own.vim b/runtime/pack/dist/opt/netrw/autoload/netrw/own.vim
deleted file mode 100644
index 9fdf85a..0000000
--- a/runtime/pack/dist/opt/netrw/autoload/netrw/own.vim
+++ /dev/null
@@ -1,61 +0,0 @@
-" FUNCTIONS IN THIS FILES ARE MENT TO BE USE BY NETRW.VIM AND NETRW.VIM ONLY.
-" THIS FUNCTIONS DON'T COMMIT TO ANY BACKWARDS COMPATABILITY. SO CHANGES AND
-" BREAKAGES IF USED OUTSIDE OF NETRW.VIM ARE EXPECTED.
-
-" General: {{{
-
-let s:deprecation_msgs = []
-function! netrw#own#Deprecate(name, version, alternatives)
-    " If running on neovim use vim.deprecate
-    if has('nvim')
-        let s:alternative = a:alternatives->get('nvim', v:null)
-        call v:lua.vim.deprecate(a:name, s:alternative, a:version, "netrw", v:false)
-        return
-    endif
-
-    " If we did notify for something only do it once
-    if s:deprecation_msgs->index(a:name) >= 0
-        return
-    endif
-
-    let s:alternative = a:alternatives->get('vim', v:null)
-    echohl WarningMsg
-    echomsg s:alternative != v:null
-                \ ? printf('%s is deprecated, use %s instead.', a:name, s:alternative)
-                \ : printf('%s is deprecated.', a:name)
-    echomsg printf('Feature will be removed in netrw %s', a:version)
-    echohl None
-
-    call add(s:deprecation_msgs, a:name)
-endfunction
-
-function! netrw#own#Open(file) abort
-    if has('nvim')
-        call luaeval('vim.ui.open(_A[1]) and nil', [a:file])
-    else
-        call dist#vim9#Open(a:file)
-    endif
-endfunction
-
-" }}}
-" Path Utilities: {{{
-
-let s:slash = &shellslash ? '/' : '\'
-
-function! netrw#own#PathJoin(...)
-    let path = ""
-
-    for arg in a:000
-        if empty(path)
-            let path = arg
-        else
-            let path .= s:slash . arg
-        endif
-    endfor
-
-    return path
-endfunction
-
-" }}}
-
-" vim:ts=8 sts=4 sw=4 et fdm=marker
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrwSettings.vim b/runtime/pack/dist/opt/netrw/autoload/netrwSettings.vim
index ba143ed..69294db 100644
--- a/runtime/pack/dist/opt/netrw/autoload/netrwSettings.vim
+++ b/runtime/pack/dist/opt/netrw/autoload/netrwSettings.vim
@@ -15,7 +15,7 @@
     finish
 endif
 
-let g:loaded_netrwSettings = "v177"
+let g:loaded_netrwSettings = "v178"
 
 " NetrwSettings: {{{
 
diff --git a/runtime/pack/dist/opt/netrw/doc/netrw.txt b/runtime/pack/dist/opt/netrw/doc/netrw.txt
index 1c291a5..f6cc0dd 100644
--- a/runtime/pack/dist/opt/netrw/doc/netrw.txt
+++ b/runtime/pack/dist/opt/netrw/doc/netrw.txt
@@ -1447,7 +1447,7 @@
 The "gn" map will take the word below the cursor and use that for
 changing the top of the tree listing.
 
-
+							*netrw-curdir*
 DELETING BOOKMARKS					*netrw-mB* {{{2
 
 To delete a bookmark, use >
diff --git a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
index 76a91b4..7a9e02a 100644
--- a/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
+++ b/runtime/pack/dist/opt/netrw/plugin/netrwPlugin.vim
@@ -15,7 +15,7 @@
     finish
 endif
 
-let g:loaded_netrwPlugin = "v177"
+let g:loaded_netrwPlugin = "v178"
 
 let s:keepcpo = &cpo
 set cpo&vim