# How to rename files with spaces in file and directory names

**URL:** <https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727>\
**Category:** General Usage\
**Tags:** question\
**Created:** [March 8, 2021, 12:19pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727 "2021-03-08T12:19:03Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 8, 2021, 12:19pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/1 "2021-03-08T12:19:03Z")

</div>

Hello,

I received a big folder with a lot of files and subfolders that have spaces in their name.

I am trying to write a function that replaces the spaces with underscore characters.

The following code does NOT work:

```julia
const BASEDIR="./input"

function rename_files(files)
    for file in files
        new_file=replace(file, " " => "_")
        if isfile(file)
            if file != new_file
                old_file=replace(file, " " => "\\ ")
                println(old_file)
                println(" ", new_file)
                mv(old_file, new_file)
            end

        else
            println("===>>> DIR")
        end

    end
end

function fix_names()
    for (root, dirs, files) in walkdir(BASEDIR)
        rename_files(joinpath.(root, files)) # files is a Vector{String}, can be empty
    end
end

fix_names()

```

The problem is that mv does not find the file it shall rename, because the name includes spaces.

Now I try to replace " " with "\ " in the old\_file name, but that also doesn’t work because the replace function gives an error in that case:

```julia
julia> file="hund hase"
"hund hase"

julia> replace(file, " " => "\ ")
ERROR: syntax: invalid escape sequence
Stacktrace:
 [1] top-level scope
   @ none:1

```

And using a double backslash also does not work.

Any idea?

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [March 8, 2021, 12:43pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/2 "2021-03-08T12:43:14Z")

</div>

Shouldn’t this just work without escaping:

```julia
julia> mv(file, new_file)
"hund_hase"

shell> ls hund_hase
hund_hase

```

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 8, 2021, 12:59pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/3 "2021-03-08T12:59:00Z")

</div>

Yes, spaces should not matter for `mv` (and should not be escaped).

@ufechner7 you should do `mv(file, ...)` (no need for `old_file`). But then there is another problem: the code tries to rename `dir 1/file 1` to `dir_1/file_1`. This is not possible since `dir_1` doesn’t exist.

So I would give `root` and `files` as two parameters to `rename_files`.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 8, 2021, 6:31pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/4 "2021-03-08T18:31:27Z")

</div>

The following code now works:

```julia
const BASEDIR="./input"

function rename_file_names(root, files)
    for file in files
        new_file=replace(file, " " => "_")
        if isfile(joinpath(root,file))
            if file != new_file
                mv(joinpath(root,file), joinpath(root,new_file))
            end
        else
            println("===>>> DIR")
        end

    end
end

function rename_dir_names(root, files)
    new_dir=replace(root, " " => "_")
    if isdir(root)
        old_dir = root
    else
        old_dir = replace(joinpath(splitpath(root)[1:end-1]...), " " => "_")
        old_dir = joinpath(old_dir, splitpath(root)[end])
    end
    if isdir(old_dir)
        if old_dir != new_dir
            mv(old_dir, new_dir)
        end
    else
        println("===>>> ERROR")
    end
end

function fix_names()
    for (root, dirs, files) in walkdir(BASEDIR)
        rename_file_names(root, files) # files is a Vector{String}, can be empty
    end   
    for (root, dirs, files) in collect(walkdir(BASEDIR))
        rename_dir_names(root, files) # files is a Vector{String}, can be empty
    end
end

fix_names()

```

But it is not generic (will fail for directories nested more than 2 levels).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 8, 2021, 6:39pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/5 "2021-03-08T18:39:05Z")

</div>

> [@ufechner7](#):
>
> `new_file=replace(file, " " => "_")`

It is ever so slightly faster (but more ‘correct’ imho) to use `Char`s instead:

```julia
new_file=replace(file, ' '=> '_')

```

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 8, 2021, 6:50pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/6 "2021-03-08T18:50:33Z")

</div>

I think it can be made generic easily by using the `topdown` option of `walkdir`, so that children are iterated before their parents. The following works according to my tests (on Linux):

```julia
function fix_names(root, names)
    for name in names
        mv(joinpath(root, name), joinpath(root, replace(name, ' ' => '_')))
   end
end

for (root, dirs, files) in walkdir("input", topdown=false)
    fix_names(root, [dirs; files])
end

```

This code misses your check for collisions though. BTW I think that check should normalize names, at least to avoid uppercase-lowercase collisions on case-insensitive filesystems.

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [March 8, 2021, 7:27pm UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/7 "2021-03-08T19:27:47Z")

</div>

> [@sijo](#):
>
> ```julia
> function fix_names(root, names)
> for name in names
> mv(joinpath(root, name), joinpath(root, replace(name, ' ' => '_')))
> end
> end
> 
> for (root, dirs, files) in walkdir("input", topdown=false)
> fix_names(root, [dirs; files])
> end
> 
> ```

Your code is so elegant!

But I need the check to make sure it also works if some of the files do NOT contain any space in the filename. This is my code now:

```julia
const BASEDIR="./input"
const DOCDIR="./doc"

function fix_names(root, names)
    for name in names
        old_name = joinpath(root, name)
        new_name = joinpath(root, replace(name, ' ' => '_'))
        if old_name != new_name
            mv(old_name, new_name)
        end
    end
end

function fix_names(dir)
    for (root, dirs, files) in walkdir(dir, topdown=false)
        fix_names(root, [dirs; files])
    end
end

fix_names(BASEDIR)
fix_names(DOCDIR)

```

Case collisions cannot happen. You will only have a collision if there is no space in the filename.

Thank you very much!

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [March 9, 2021, 7:43am UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/8 "2021-03-09T07:43:04Z")

</div>

Oh indeed in my test case every file and directory had spaces 🙂

You can still have collisions if a directory contains both `file 1` and `file_1`: if you rename the first file it will overwrite the second one. And on Windows and MacOS, `file_1` and `File_1` are the same file so renaming `file 1` can collide with `File_1`…

---

<div class="post-metadata">

**Author:** ![hillelawaskar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hillelawaskar/32/26276_2.png) [@hillelawaskar](https://discourse.julialang.org/u/hillelawaskar)\
**Post date:** [June 20, 2021, 10:42am UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/9 "2021-06-20T10:42:13Z")

</div>

Adding as a way to rename file in same directory

#Jun20,2021 : Rename files in one single folder  
const BASEDIR=“/home/hillel/workjulspace/testdata/B”  
files = readdir(BASEDIR, join=true, sort = true)  
filenames = readdir(BASEDIR,sort = true)  
#println(files)  
#println(filenames)  
#println(files)  
img\_files = filter(endswith(“.png”),files)  
for (i,file) in enumerate(img\_files)  
#println(i)  
#println(file)  
mv(file,“/home/hillel/workjulspace/testdata/B/BB\_$(filenames[i])”)  
end

---

<div class="post-metadata">

**Author:** ![hillelawaskar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hillelawaskar/32/26276_2.png) [@hillelawaskar](https://discourse.julialang.org/u/hillelawaskar)\
**Post date:** [June 20, 2021, 10:42am UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/10 "2021-06-20T10:42:54Z")

</div>

#Jun20,2021 : Rename files in one single folder

```julia
const BASEDIR="/home/hillel/workjulspace/testdata/B"
files = readdir(BASEDIR, join=true, sort = true)
filenames = readdir(BASEDIR,sort = true)
#println(files)
#println(filenames)
#println(files)
img_files = filter(endswith(".png"),files)
for (i,file) in enumerate(img_files)
    #println(i)
    #println(file)
    mv(file,"/home/hillel/workjulspace/testdata/B/BB_$(filenames[i])")
end

```

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [June 20, 2021, 10:50am UTC](https://discourse.julialang.org/t/how-to-rename-files-with-spaces-in-file-and-directory-names/56727/11 "2021-06-20T10:50:12Z")

</div>

Please put triple quotes around you code examples, like this:  
```julia

```
