Bash & 将相对路径转换为绝对路径的 Perl 脚本
Bash & Perl script to convert relative paths to absolute paths
我有一个顶级目录路径,我想递归地将所有相对路径转换为存在于该目录内所有文件中的绝对路径。
例如我有这个目录结构:
$ tree
.
|-- DIR
| |-- inner_level.ext1
| `-- inner_level.ext2
|-- top_level.ext1
`-- top_level.ext2
top_level.ext1
的内容:
../../a/b/c/filename_1.txt
../../a/d/e/filename_2.txt
假设顶级目录路径是 /this/is/the/abs/dir/path/
想要将top_level.ext1
的内容转换为:
/this/is/the/abs/a/b/c/filename_1.txt
/this/is/the/abs/a/d/e/filename_2.txt
top_level.ext2
的内容:
cc_include+=-I../../util1/src/module1/moduleController -I../../util/src/module1/module2Controller;
cc_include+=-I../../util2/src/module2/moduleUtility;
想要将top_level.ext2
的内容转换为:
cc_include+=-I/this/is/the/abs/util1/src/module1/moduleController -I/this/is/the/abs/util/src/module1/module2Controller;
cc_include+=-I/this/is/the/abs/util2/src/module2/moduleUtility;
另外,想对 DIR 内的文件应用同样的转换。
例如
DIR/inner_level.ext1
的内容:
../../../a/b/c/filename_1.txt
../../../a/d/e/filename_2.txt
想要将DIR/inner_level.ext1
的内容转换为:
/this/is/the/abs/a/b/c/filename_1.txt
/this/is/the/abs/a/d/e/filename_2.txt
DIR/inner_level.ext2
也一样。
写了这两个脚本。
top_level.ext1
的转换工作成功。
file_manager.sh
:
#!/usr/bin/bash
file='resolve_path.pl'
basedir='/this/is/the/abs/dir/path'
run_perl(){
echo -e "\n File getting modified: "
cp tmp.in
perl $file
mv tmp.out
rm tmp.in
}
find $basedir -type f |while read inputfile
do
run_perl $inputfile
done
resolve_path.pl
:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use 5.010;
use Switch;
#******************************************************
# Set-up Directory And Input/Output File Names
#******************************************************
our $in_file = glob('tmp.in');
my $out_file1 = 'tmp.out';
print "Input file: $in_file\n";
#************************************
# Local and Global Variables
#*************************************
my $current_path = "/this/is/the/abs/dir/path";
my $temp_path = $current_path;
#************************************
# Open Read and Write File
#************************************
open(READ, $in_file) || die "cannot open $in_file";
open(WRITE, ">$out_file1") || die "cannot open $out_file1";
#******************************************************
# Read The Input [*.out] File Line By Line
#******************************************************
while (<READ>) {
if(/^(\.\.\/){1,}(\w+\/)*(\w+).(\w+)/){
my $file_name = ;
my $file_ext = ;
my @count = ($_ =~ /\.\.\//g);
my $cnt = @count;
my @prev_dir = ($_ =~ /\w+\//g);
my $prev_dir_cnt = @prev_dir;
my $file_prev_dir = join('', @prev_dir);
$temp_path = $current_path;
for(my $i=0; $i<$cnt; $i++){
if($temp_path =~m/(\/.*)\/\w+/){
$temp_path = ;
}
}
print WRITE "$temp_path"."\/"."$file_prev_dir"."$file_name"."\."."$file_ext"."\n";
} else {
print WRITE "$_";
}
}
我面临的问题:
未对 top_level.ext2
和 DIR/inner_level.ext2
应用转换
因为我的 Perl 脚本没有正确解析 ../
es(即
cc_include+=-I
开头来了)。
从相对路径到绝对路径的转换无效
适合 DIR/inner_level.ext1
并且路径错误
附加.
如果有人可以在我的脚本中提出预期的更改以解决上述两个问题,那将很有帮助。
为什么是 2 个脚本?那是低效的。
Perl 完全能够检索文件列表,并且具有简化该过程的模块以及用于解析和更改路径的模块。
File::Find - Traverse a directory tree.
File::Find::Rule - Alternative interface to File::Find
File::Basename - Parse file paths into directory, filename and suffix.
我有一个顶级目录路径,我想递归地将所有相对路径转换为存在于该目录内所有文件中的绝对路径。 例如我有这个目录结构:
$ tree
.
|-- DIR
| |-- inner_level.ext1
| `-- inner_level.ext2
|-- top_level.ext1
`-- top_level.ext2
top_level.ext1
的内容:
../../a/b/c/filename_1.txt
../../a/d/e/filename_2.txt
假设顶级目录路径是 /this/is/the/abs/dir/path/
想要将top_level.ext1
的内容转换为:
/this/is/the/abs/a/b/c/filename_1.txt
/this/is/the/abs/a/d/e/filename_2.txt
top_level.ext2
的内容:
cc_include+=-I../../util1/src/module1/moduleController -I../../util/src/module1/module2Controller;
cc_include+=-I../../util2/src/module2/moduleUtility;
想要将top_level.ext2
的内容转换为:
cc_include+=-I/this/is/the/abs/util1/src/module1/moduleController -I/this/is/the/abs/util/src/module1/module2Controller;
cc_include+=-I/this/is/the/abs/util2/src/module2/moduleUtility;
另外,想对 DIR 内的文件应用同样的转换。
例如
DIR/inner_level.ext1
的内容:
../../../a/b/c/filename_1.txt
../../../a/d/e/filename_2.txt
想要将DIR/inner_level.ext1
的内容转换为:
/this/is/the/abs/a/b/c/filename_1.txt
/this/is/the/abs/a/d/e/filename_2.txt
DIR/inner_level.ext2
也一样。
写了这两个脚本。
top_level.ext1
的转换工作成功。
file_manager.sh
:
#!/usr/bin/bash
file='resolve_path.pl'
basedir='/this/is/the/abs/dir/path'
run_perl(){
echo -e "\n File getting modified: "
cp tmp.in
perl $file
mv tmp.out
rm tmp.in
}
find $basedir -type f |while read inputfile
do
run_perl $inputfile
done
resolve_path.pl
:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use 5.010;
use Switch;
#******************************************************
# Set-up Directory And Input/Output File Names
#******************************************************
our $in_file = glob('tmp.in');
my $out_file1 = 'tmp.out';
print "Input file: $in_file\n";
#************************************
# Local and Global Variables
#*************************************
my $current_path = "/this/is/the/abs/dir/path";
my $temp_path = $current_path;
#************************************
# Open Read and Write File
#************************************
open(READ, $in_file) || die "cannot open $in_file";
open(WRITE, ">$out_file1") || die "cannot open $out_file1";
#******************************************************
# Read The Input [*.out] File Line By Line
#******************************************************
while (<READ>) {
if(/^(\.\.\/){1,}(\w+\/)*(\w+).(\w+)/){
my $file_name = ;
my $file_ext = ;
my @count = ($_ =~ /\.\.\//g);
my $cnt = @count;
my @prev_dir = ($_ =~ /\w+\//g);
my $prev_dir_cnt = @prev_dir;
my $file_prev_dir = join('', @prev_dir);
$temp_path = $current_path;
for(my $i=0; $i<$cnt; $i++){
if($temp_path =~m/(\/.*)\/\w+/){
$temp_path = ;
}
}
print WRITE "$temp_path"."\/"."$file_prev_dir"."$file_name"."\."."$file_ext"."\n";
} else {
print WRITE "$_";
}
}
我面临的问题:
未对
top_level.ext2
和DIR/inner_level.ext2
应用转换 因为我的 Perl 脚本没有正确解析../
es(即cc_include+=-I
开头来了)。从相对路径到绝对路径的转换无效 适合
DIR/inner_level.ext1
并且路径错误 附加.
如果有人可以在我的脚本中提出预期的更改以解决上述两个问题,那将很有帮助。
为什么是 2 个脚本?那是低效的。
Perl 完全能够检索文件列表,并且具有简化该过程的模块以及用于解析和更改路径的模块。
File::Find - Traverse a directory tree.
File::Find::Rule - Alternative interface to File::Find
File::Basename - Parse file paths into directory, filename and suffix.