如何将所有隐藏的 folders/files 更改为在多个子目录中可见
How to change all hidden folders/files to visible in a multiple sub directories
我在一个目录中有数百个子目录,其中都有隐藏文件,我需要删除它们开头的句点以使它们可见。我找到了一个进入每个目录并更改它们以使它们可见的命令,但我需要知道如何使该命令从一个目录向上运行。
rename 's/\.//;' .*
我已经尝试了大约一个小时来修改它以使其工作更上一层楼,但我对 Perl 字符串的理解还不足以做到这一点。如果有人能帮忙,我相信这很简单,我就是找不到正确的答案。
safely_unhide
:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename qw( fileparse );
for (@ARGV) {
my $o = $_;
my ($fn, $dir_qfn) = fileparse($_);
$fn =~ s/^\.//
or next;
my $n = "$dir_qfn/$fn";
if (stat($n)) {
warn("Skipping \"$o\": \"$n\" already exists\n");
next;
}
elsif (!$!{ENOENT}) {
warn("Skipping \"$o\": Can't stat \"$n\": $!\n");
next;
}
rename($n, $o)
or warn("Skipping \"$o\": Can't rename to \"$n\": $!\n");
}
用法:
find -type f -exec safely_unhide {} + # Supports all file names. Requires GNU find
find -type f | xargs safely_unhide # Doesn't support newlines in file names.
find -type f -print0 | xargs -0 safely_unhide # Supports all file names.
如果您也想重命名隐藏目录,请删除 -type f
并添加 -depth
。
这需要一个支持 +
的查找(可以使用 \;
代替,它将多次调用 rename
),但即使 POSIX find 指定它:
find -mindepth 1 -depth -exec rename -n 's{/\.([^\/]*$)}{/}' {} +
-depth
选项可防止在重命名目录中的所有文件之前重命名目录
-mindepth 1
阻止 find 尝试重命名当前目录,.
.
-n
只是打印要重命名的内容而不是实际重命名(必须删除才能重命名)。
- 如果前面有正斜杠,则正则表达式会删除最后一个没有正斜杠的句点。
rename
不会覆盖现有文件,除非使用 -f
("force") 选项。
对于这样的测试目录结构:
.
├── .dir1
│ ├── .dir2
│ │ ├── .dir3
│ │ │ └── .file2
│ │ └── .file1
│ ├── file3
│ └── .file6
├── dir5
│ └── .file5
├── .file4
├── test1.bar
└── test1.foo
输出是
rename(./dir5/.file5, ./dir5/file5)
rename(./.file4, ./file4)
rename(./.dir1/.file6, ./.dir1/file6)
rename(./.dir1/.dir2/.file1, ./.dir1/.dir2/file1)
rename(./.dir1/.dir2/.dir3/.file2, ./.dir1/.dir2/.dir3/file2)
rename(./.dir1/.dir2/.dir3, ./.dir1/.dir2/dir3)
rename(./.dir1/.dir2, ./.dir1/dir2)
rename(./.dir1, ./dir1)
删除-n
后的结果是
.
├── dir1
│ ├── dir2
│ │ ├── dir3
│ │ │ └── file2
│ │ └── file1
│ ├── file3
│ └── file6
├── dir5
│ └── file5
├── file4
├── test1.bar
└── test1.foo
我在一个目录中有数百个子目录,其中都有隐藏文件,我需要删除它们开头的句点以使它们可见。我找到了一个进入每个目录并更改它们以使它们可见的命令,但我需要知道如何使该命令从一个目录向上运行。
rename 's/\.//;' .*
我已经尝试了大约一个小时来修改它以使其工作更上一层楼,但我对 Perl 字符串的理解还不足以做到这一点。如果有人能帮忙,我相信这很简单,我就是找不到正确的答案。
safely_unhide
:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename qw( fileparse );
for (@ARGV) {
my $o = $_;
my ($fn, $dir_qfn) = fileparse($_);
$fn =~ s/^\.//
or next;
my $n = "$dir_qfn/$fn";
if (stat($n)) {
warn("Skipping \"$o\": \"$n\" already exists\n");
next;
}
elsif (!$!{ENOENT}) {
warn("Skipping \"$o\": Can't stat \"$n\": $!\n");
next;
}
rename($n, $o)
or warn("Skipping \"$o\": Can't rename to \"$n\": $!\n");
}
用法:
find -type f -exec safely_unhide {} + # Supports all file names. Requires GNU find
find -type f | xargs safely_unhide # Doesn't support newlines in file names.
find -type f -print0 | xargs -0 safely_unhide # Supports all file names.
如果您也想重命名隐藏目录,请删除 -type f
并添加 -depth
。
这需要一个支持 +
的查找(可以使用 \;
代替,它将多次调用 rename
),但即使 POSIX find 指定它:
find -mindepth 1 -depth -exec rename -n 's{/\.([^\/]*$)}{/}' {} +
-depth
选项可防止在重命名目录中的所有文件之前重命名目录-mindepth 1
阻止 find 尝试重命名当前目录,.
.-n
只是打印要重命名的内容而不是实际重命名(必须删除才能重命名)。- 如果前面有正斜杠,则正则表达式会删除最后一个没有正斜杠的句点。
rename
不会覆盖现有文件,除非使用 -f
("force") 选项。
对于这样的测试目录结构:
.
├── .dir1
│ ├── .dir2
│ │ ├── .dir3
│ │ │ └── .file2
│ │ └── .file1
│ ├── file3
│ └── .file6
├── dir5
│ └── .file5
├── .file4
├── test1.bar
└── test1.foo
输出是
rename(./dir5/.file5, ./dir5/file5)
rename(./.file4, ./file4)
rename(./.dir1/.file6, ./.dir1/file6)
rename(./.dir1/.dir2/.file1, ./.dir1/.dir2/file1)
rename(./.dir1/.dir2/.dir3/.file2, ./.dir1/.dir2/.dir3/file2)
rename(./.dir1/.dir2/.dir3, ./.dir1/.dir2/dir3)
rename(./.dir1/.dir2, ./.dir1/dir2)
rename(./.dir1, ./dir1)
删除-n
后的结果是
.
├── dir1
│ ├── dir2
│ │ ├── dir3
│ │ │ └── file2
│ │ └── file1
│ ├── file3
│ └── file6
├── dir5
│ └── file5
├── file4
├── test1.bar
└── test1.foo