1

I have directory structure like the following:

. ├── ParentDirectory │   ├── ChildDirectory1 │   │   ├── 01-File.txt │   │   ├── 02-File.txt │   │   ├── 03-File.adoc │   │   ├── 04-File.md │   │   └── 05-File.txt │   ├── ChildDirectory2 │   │   ├── 01-File.txt │   │   ├── 02-File.txt │   │   ├── 03-File.adoc │   │   ├── 04-File.txt │   │   ├── 05-File.txt │   │   └── 06-File.md │   ├── ChildDirectory3 │   │   ├── 01-File.txt │   │   ├── 02-File.txt │   │   ├── 03-File.adoc │   │   ├── 04-File.md │   │   ├── 05-File.md │   │   └── 06-File.txt 

You may have noticed that some file and directory has leading whitespace. What you may not have noticed is some file and directory has trailing whitespace as well.

For trailing whitespace I tried:

% find . -exec rename 's/ *$//' {} + 

I have to run this command multiple times. On first run it rename parent directory. On second run it rename the child. My directory structure actually goes much deeper. So, running a command multiple times is not a good solution.

For leading whitespace find . -exec rename 's/^ *//' {} + does not work at all.

How can I remove all leading and trailing whitespace from both file and directory names recursively?

7
  • 2
    Did you try depth-first search? You can do that by supplying the -depth flag to find. Commented Dec 12, 2020 at 7:04
  • Yes now find . -depth -exec rename 's/^ *//' {} + works. Still find . -depth -exec rename 's/^ *//' {} + not working. Commented Dec 12, 2020 at 7:47
  • @blueray You just said that a command was and was not working, at the same time. Commented Dec 12, 2020 at 9:07
  • Also, at no point do you actually say what "not working" means. Does it produce errors? What are those errors? Does it rename files in the wrong manner? Not at all? Does your filenames contain tab characters? Commented Dec 12, 2020 at 9:08
  • @Kusalananda the command runs without any error. But it does not remove the leading whitespace. Commented Dec 12, 2020 at 9:55

2 Answers 2

2

With zsh:

autoload -Uz zmv # best in ~/.zshrc zmv -n '(**/)(*)' '$1${${2##[[:space:]]#}%%[[:space:]]#}' 

(remove -n (dry-run) if happy).

Add a (#qD) at the end of the pattern, if you also want to process hidden files and files in hidden directories.

With rename, that would be something like:

find . -depth ! -name . -exec rename -n ' my ($dir, $base) = m{(.*)/(.*)}s; $base =~ s/^\s*//; $base =~ s/\s*$//; $_ = "$dir/$base";' {} + 

Though note that \s (contrary to zsh's [[:space:]]) only matches on ASCII whitespace, not the other whitespace characters in your locale. rename also doesn't have any of zmv's safeguards to check for conflicts before starting the renaming.

In any case, note that on several systems, including GNU ones, the non-breaking-space character (U+00A0) is not considered whitespace on the ground that it's not meant to delimit words, so it won't be removed, even with the zmv approach. If you have such characters, you could strip them with:

zmv -n '(**/)(*)' $'$1${${2##[[:space:]\ua0]#}%%[[:space:]\ua0]#}' 
3
  • By the way, what does my ($dir, $base) = m{(.*)/(.*)}s; do? Commented Dec 12, 2020 at 7:57
  • 1
    @blueray, it splits the path into directory ($dir) and filename ($base) parts to get the equivalent of $1 and $2 in zmv. Commented Dec 12, 2020 at 8:00
  • Thank you very much. Commented Dec 12, 2020 at 8:01
0

With python :

Removing leading and trailing whitespaces was a subtopic in my research for migrating Apple servers or replacing Netatalk as a file service by Samba on linux. As there was nothing around solving all naming issues, I ended up writing a python script to do my bidding. Although I tested this only on linux, it should work on any posix system providing python 3.

You can find the code on my git: macSanitize

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.