Try to learn about shell script

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite












I try to learn a new skill for shell script. So now I receive a lesson from my teacher about move file to new directory.



Question



There is a file pattern



A_20180423_0015 B_20180501_0045 C_20180426_0045 


and want to moving files to those directories like /new/destpath/A/20180423/0015,0030,0045 each directory have a 3 files



in my script i write



 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..


and i try to figure it out to use loop or it else but i don't know which use to select each file to each directory.







share|improve this question





















  • Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
    – nohillside
    May 4 at 6:22














up vote
1
down vote

favorite












I try to learn a new skill for shell script. So now I receive a lesson from my teacher about move file to new directory.



Question



There is a file pattern



A_20180423_0015 B_20180501_0045 C_20180426_0045 


and want to moving files to those directories like /new/destpath/A/20180423/0015,0030,0045 each directory have a 3 files



in my script i write



 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..


and i try to figure it out to use loop or it else but i don't know which use to select each file to each directory.







share|improve this question





















  • Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
    – nohillside
    May 4 at 6:22












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I try to learn a new skill for shell script. So now I receive a lesson from my teacher about move file to new directory.



Question



There is a file pattern



A_20180423_0015 B_20180501_0045 C_20180426_0045 


and want to moving files to those directories like /new/destpath/A/20180423/0015,0030,0045 each directory have a 3 files



in my script i write



 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..


and i try to figure it out to use loop or it else but i don't know which use to select each file to each directory.







share|improve this question













I try to learn a new skill for shell script. So now I receive a lesson from my teacher about move file to new directory.



Question



There is a file pattern



A_20180423_0015 B_20180501_0045 C_20180426_0045 


and want to moving files to those directories like /new/destpath/A/20180423/0015,0030,0045 each directory have a 3 files



in my script i write



 #! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir $itype_$(date --date "$i day ago" +"%Y%m%d")_00$itime ;done;done;done)
cd ..


and i try to figure it out to use loop or it else but i don't know which use to select each file to each directory.









share|improve this question












share|improve this question




share|improve this question








edited May 4 at 9:30









Vlastimil

6,3211146116




6,3211146116









asked May 4 at 4:11









Dnop

83




83











  • Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
    – nohillside
    May 4 at 6:22
















  • Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
    – nohillside
    May 4 at 6:22















Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
– nohillside
May 4 at 6:22




Can you add some more details about what exactly the pattern is, where the files are currently stored, and how the target structure will look like (an example would help a lot here)? Also, do you need MakesubA later on in your script for something?
– nohillside
May 4 at 6:22










1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










You have files that basically have a destination path encoded in their filenames.



The file called A_20180423_0015 should be moved to A/20180423/0015 (I'm assuming 0015 is the new name of the file in the directory A/20180423), which is a pathname that is the same as the original filename but with the underscores replaced by slashes.



This means that this exercise is about replacing characters in strings.



There is no need to go through and create destination directories for every single possible date because the destination is already encoded in the filename of the files.



I'm not entirely sure where the original files are located, or whether you can just use [A-Z]_*_* as a pattern to match them in the current directory (I'm going to assume you can).



for source_filename in [A-Z]_*_*; do
target_pathname=$source_filename//_//
mkdir -p "$target_pathname%/*"
mv "$source_filename" "$target_pathname"
done


If we start out with



.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files


... and run the above code, then we'll end up with



.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045

6 directories, 3 files


Annotated code:



# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's $parameter//pattern/replacement pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/$source_filename//_//"
target_pathname=$source_filename//_//

# Make sure that the target directory exists.
# With $target_pathname%/* we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "$target_pathname%/*"

# Move the file into place.
mv "$source_filename" "$target_pathname"
done



If I have misunderstood the question and the files should retain their original filenames, but be moved into directories corresponding to the filename, i.e. A_20180423_0015 should be moved to A/20180423/0015/A_20180423_0015, then we only have to change a few characters in the code above:



mkdir -p "$target_pathname%/*"


changes to



mkdir -p "$target_pathname"


This change would give us



.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045

9 directories, 3 files



For the case when the source files are located in another directory than the current one:



for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=$source_pathname##*/
target_pathname="some/target/path/$source_filename//_//"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done





share|improve this answer























  • I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
    – Dnop
    May 4 at 7:46










  • @Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
    – Kusalananda
    May 4 at 7:52










  • Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
    – Dnop
    May 4 at 8:05











  • @Dnop See updated answer.
    – Kusalananda
    May 4 at 8:33










  • If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
    – Dnop
    May 4 at 8:41











Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f441695%2ftry-to-learn-about-shell-script%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










You have files that basically have a destination path encoded in their filenames.



The file called A_20180423_0015 should be moved to A/20180423/0015 (I'm assuming 0015 is the new name of the file in the directory A/20180423), which is a pathname that is the same as the original filename but with the underscores replaced by slashes.



This means that this exercise is about replacing characters in strings.



There is no need to go through and create destination directories for every single possible date because the destination is already encoded in the filename of the files.



I'm not entirely sure where the original files are located, or whether you can just use [A-Z]_*_* as a pattern to match them in the current directory (I'm going to assume you can).



for source_filename in [A-Z]_*_*; do
target_pathname=$source_filename//_//
mkdir -p "$target_pathname%/*"
mv "$source_filename" "$target_pathname"
done


If we start out with



.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files


... and run the above code, then we'll end up with



.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045

6 directories, 3 files


Annotated code:



# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's $parameter//pattern/replacement pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/$source_filename//_//"
target_pathname=$source_filename//_//

# Make sure that the target directory exists.
# With $target_pathname%/* we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "$target_pathname%/*"

# Move the file into place.
mv "$source_filename" "$target_pathname"
done



If I have misunderstood the question and the files should retain their original filenames, but be moved into directories corresponding to the filename, i.e. A_20180423_0015 should be moved to A/20180423/0015/A_20180423_0015, then we only have to change a few characters in the code above:



mkdir -p "$target_pathname%/*"


changes to



mkdir -p "$target_pathname"


This change would give us



.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045

9 directories, 3 files



For the case when the source files are located in another directory than the current one:



for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=$source_pathname##*/
target_pathname="some/target/path/$source_filename//_//"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done





share|improve this answer























  • I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
    – Dnop
    May 4 at 7:46










  • @Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
    – Kusalananda
    May 4 at 7:52










  • Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
    – Dnop
    May 4 at 8:05











  • @Dnop See updated answer.
    – Kusalananda
    May 4 at 8:33










  • If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
    – Dnop
    May 4 at 8:41















up vote
2
down vote



accepted










You have files that basically have a destination path encoded in their filenames.



The file called A_20180423_0015 should be moved to A/20180423/0015 (I'm assuming 0015 is the new name of the file in the directory A/20180423), which is a pathname that is the same as the original filename but with the underscores replaced by slashes.



This means that this exercise is about replacing characters in strings.



There is no need to go through and create destination directories for every single possible date because the destination is already encoded in the filename of the files.



I'm not entirely sure where the original files are located, or whether you can just use [A-Z]_*_* as a pattern to match them in the current directory (I'm going to assume you can).



for source_filename in [A-Z]_*_*; do
target_pathname=$source_filename//_//
mkdir -p "$target_pathname%/*"
mv "$source_filename" "$target_pathname"
done


If we start out with



.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files


... and run the above code, then we'll end up with



.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045

6 directories, 3 files


Annotated code:



# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's $parameter//pattern/replacement pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/$source_filename//_//"
target_pathname=$source_filename//_//

# Make sure that the target directory exists.
# With $target_pathname%/* we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "$target_pathname%/*"

# Move the file into place.
mv "$source_filename" "$target_pathname"
done



If I have misunderstood the question and the files should retain their original filenames, but be moved into directories corresponding to the filename, i.e. A_20180423_0015 should be moved to A/20180423/0015/A_20180423_0015, then we only have to change a few characters in the code above:



mkdir -p "$target_pathname%/*"


changes to



mkdir -p "$target_pathname"


This change would give us



.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045

9 directories, 3 files



For the case when the source files are located in another directory than the current one:



for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=$source_pathname##*/
target_pathname="some/target/path/$source_filename//_//"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done





share|improve this answer























  • I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
    – Dnop
    May 4 at 7:46










  • @Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
    – Kusalananda
    May 4 at 7:52










  • Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
    – Dnop
    May 4 at 8:05











  • @Dnop See updated answer.
    – Kusalananda
    May 4 at 8:33










  • If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
    – Dnop
    May 4 at 8:41













up vote
2
down vote



accepted







up vote
2
down vote



accepted






You have files that basically have a destination path encoded in their filenames.



The file called A_20180423_0015 should be moved to A/20180423/0015 (I'm assuming 0015 is the new name of the file in the directory A/20180423), which is a pathname that is the same as the original filename but with the underscores replaced by slashes.



This means that this exercise is about replacing characters in strings.



There is no need to go through and create destination directories for every single possible date because the destination is already encoded in the filename of the files.



I'm not entirely sure where the original files are located, or whether you can just use [A-Z]_*_* as a pattern to match them in the current directory (I'm going to assume you can).



for source_filename in [A-Z]_*_*; do
target_pathname=$source_filename//_//
mkdir -p "$target_pathname%/*"
mv "$source_filename" "$target_pathname"
done


If we start out with



.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files


... and run the above code, then we'll end up with



.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045

6 directories, 3 files


Annotated code:



# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's $parameter//pattern/replacement pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/$source_filename//_//"
target_pathname=$source_filename//_//

# Make sure that the target directory exists.
# With $target_pathname%/* we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "$target_pathname%/*"

# Move the file into place.
mv "$source_filename" "$target_pathname"
done



If I have misunderstood the question and the files should retain their original filenames, but be moved into directories corresponding to the filename, i.e. A_20180423_0015 should be moved to A/20180423/0015/A_20180423_0015, then we only have to change a few characters in the code above:



mkdir -p "$target_pathname%/*"


changes to



mkdir -p "$target_pathname"


This change would give us



.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045

9 directories, 3 files



For the case when the source files are located in another directory than the current one:



for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=$source_pathname##*/
target_pathname="some/target/path/$source_filename//_//"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done





share|improve this answer















You have files that basically have a destination path encoded in their filenames.



The file called A_20180423_0015 should be moved to A/20180423/0015 (I'm assuming 0015 is the new name of the file in the directory A/20180423), which is a pathname that is the same as the original filename but with the underscores replaced by slashes.



This means that this exercise is about replacing characters in strings.



There is no need to go through and create destination directories for every single possible date because the destination is already encoded in the filename of the files.



I'm not entirely sure where the original files are located, or whether you can just use [A-Z]_*_* as a pattern to match them in the current directory (I'm going to assume you can).



for source_filename in [A-Z]_*_*; do
target_pathname=$source_filename//_//
mkdir -p "$target_pathname%/*"
mv "$source_filename" "$target_pathname"
done


If we start out with



.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045

0 directory, 3 files


... and run the above code, then we'll end up with



.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045

6 directories, 3 files


Annotated code:



# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's $parameter//pattern/replacement pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/$source_filename//_//"
target_pathname=$source_filename//_//

# Make sure that the target directory exists.
# With $target_pathname%/* we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "$target_pathname%/*"

# Move the file into place.
mv "$source_filename" "$target_pathname"
done



If I have misunderstood the question and the files should retain their original filenames, but be moved into directories corresponding to the filename, i.e. A_20180423_0015 should be moved to A/20180423/0015/A_20180423_0015, then we only have to change a few characters in the code above:



mkdir -p "$target_pathname%/*"


changes to



mkdir -p "$target_pathname"


This change would give us



.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045

9 directories, 3 files



For the case when the source files are located in another directory than the current one:



for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=$source_pathname##*/
target_pathname="some/target/path/$source_filename//_//"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done






share|improve this answer















share|improve this answer



share|improve this answer








edited May 4 at 8:32


























answered May 4 at 6:31









Kusalananda

102k13199316




102k13199316











  • I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
    – Dnop
    May 4 at 7:46










  • @Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
    – Kusalananda
    May 4 at 7:52










  • Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
    – Dnop
    May 4 at 8:05











  • @Dnop See updated answer.
    – Kusalananda
    May 4 at 8:33










  • If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
    – Dnop
    May 4 at 8:41

















  • I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
    – Dnop
    May 4 at 7:46










  • @Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
    – Kusalananda
    May 4 at 7:52










  • Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
    – Dnop
    May 4 at 8:05











  • @Dnop See updated answer.
    – Kusalananda
    May 4 at 8:33










  • If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
    – Dnop
    May 4 at 8:41
















I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
– Dnop
May 4 at 7:46




I try to adapt a script like add a path on source_file and target folder but result is A B C D DEST_PATH folder A B C D not in a folder target folder
– Dnop
May 4 at 7:46












@Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
– Kusalananda
May 4 at 7:52




@Dnop Sorry, but I don't understand what you are saying. Do you need to access the original files in another location than the current directory?
– Kusalananda
May 4 at 7:52












Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
– Dnop
May 4 at 8:05





Yes. This is a adapt script, I add a path for source_file and target file #for source_filename in /app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/DEST_PATH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done but it not work
– Dnop
May 4 at 8:05













@Dnop See updated answer.
– Kusalananda
May 4 at 8:33




@Dnop See updated answer.
– Kusalananda
May 4 at 8:33












If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
– Dnop
May 4 at 8:41





If i add a path, script is error [serveradm@DSNJENKA002G TEST_GRAPH]$ bash movefile.bash mv: cannot stat €/app/D_GRPAH/TEST_GRAPH/LAB2/[A-Z]__*€: No such file or directory but if i don't add a path. It work on your shell script but i try add a path #for source_filename in [A-Z]__*; do # target_pathname="/app/D_GRAPH/TEST_GRAPH/$source_filename//_//" # mkdir -p "$target_pathname" # mv "$source_filename" "$target_pathname" #done a result folder A B C D. It isn't in a DEST_PATH.
– Dnop
May 4 at 8:41













 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f441695%2ftry-to-learn-about-shell-script%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Peggy Mitchell

Palaiologos

The Forum (Inglewood, California)