“cp: target '…’ is not a directory” during while loop The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) 2019 Community Moderator Election ResultsWhy does my shell script choke on whitespace or other special characters?Why is looping over find's output bad practice?Understanding the -exec option of `find`Optimizing a `while` loopcp --no-target-directory explainedWhile loop stuck in infinite loopwhile: command not foundcp directory with permissions but not recursivelykill background while loopLoop space directory nameDefine target directory with flag in `scp` or `rsync` (like `cp -t`)How to make ctrl+c /not/ interrupt the while-loop?While Loop over a File returning command not found
How to support a colleague who finds meetings extremely tiring?
Identify 80s or 90s comics with ripped creatures (not dwarves)
Can each chord in a progression create its own key?
60's-70's movie: home appliances revolting against the owners
What happens to a Warlock's expended Spell Slots when they gain a Level?
Do I have Disadvantage attacking with an off-hand weapon?
Is there a way to generate uniformly distributed points on a sphere from a fixed amount of random real numbers per point?
Match Roman Numerals
Can the DM override racial traits?
How to handle characters who are more educated than the author?
Is it ethical to upload a automatically generated paper to a non peer-reviewed site as part of a larger research?
Are spiders unable to hurt humans, especially very small spiders?
how can a perfect fourth interval be considered either consonant or dissonant?
should truth entail possible truth
How do you keep chess fun when your opponent constantly beats you?
What to do when moving next to a bird sanctuary with a loosely-domesticated cat?
Simulating Exploding Dice
Is this wall load bearing? Blueprints and photos attached
Did the UK government pay "millions and millions of dollars" to try to snag Julian Assange?
Button changing its text & action. Good or terrible?
Intergalactic human space ship encounters another ship, character gets shunted off beyond known universe, reality starts collapsing
What other Star Trek series did the main TNG cast show up in?
Is every episode of "Where are my Pants?" identical?
A phrase ”follow into" in a context
“cp: target '…’ is not a directory” during while loop
The 2019 Stack Overflow Developer Survey Results Are In
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)
2019 Community Moderator Election ResultsWhy does my shell script choke on whitespace or other special characters?Why is looping over find's output bad practice?Understanding the -exec option of `find`Optimizing a `while` loopcp --no-target-directory explainedWhile loop stuck in infinite loopwhile: command not foundcp directory with permissions but not recursivelykill background while loopLoop space directory nameDefine target directory with flag in `scp` or `rsync` (like `cp -t`)How to make ctrl+c /not/ interrupt the while-loop?While Loop over a File returning command not found
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have a directory of files whose names I want to shorten:
(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew 4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew 4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc
I ran the following from the command line:
while read x; do echo cp '$x' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)
which produced what I expected:
cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc
However, removing the echo gives:
cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc
I'm guessing it's something to do with spaces in the file names, but I would have thought the single-quotes would have taken care of that?
I've tried doing a copy/paste of the output of the echo back into the terminal, and it runs OK! It just won't run in the while loop.
Versions:
(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
bash quoting cp
New contributor
add a comment |
I have a directory of files whose names I want to shorten:
(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew 4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew 4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc
I ran the following from the command line:
while read x; do echo cp '$x' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)
which produced what I expected:
cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc
However, removing the echo gives:
cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc
I'm guessing it's something to do with spaces in the file names, but I would have thought the single-quotes would have taken care of that?
I've tried doing a copy/paste of the output of the echo back into the terminal, and it runs OK! It just won't run in the while loop.
Versions:
(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
bash quoting cp
New contributor
add a comment |
I have a directory of files whose names I want to shorten:
(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew 4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew 4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc
I ran the following from the command line:
while read x; do echo cp '$x' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)
which produced what I expected:
cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc
However, removing the echo gives:
cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc
I'm guessing it's something to do with spaces in the file names, but I would have thought the single-quotes would have taken care of that?
I've tried doing a copy/paste of the output of the echo back into the terminal, and it runs OK! It just won't run in the while loop.
Versions:
(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
bash quoting cp
New contributor
I have a directory of files whose names I want to shorten:
(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew 4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew 4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc
I ran the following from the command line:
while read x; do echo cp '$x' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)
which produced what I expected:
cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc
However, removing the echo gives:
cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc
I'm guessing it's something to do with spaces in the file names, but I would have thought the single-quotes would have taken care of that?
I've tried doing a copy/paste of the output of the echo back into the terminal, and it runs OK! It just won't run in the while loop.
Versions:
(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
bash quoting cp
bash quoting cp
New contributor
New contributor
New contributor
asked yesterday
Andrew WoodwardAndrew Woodward
132
132
New contributor
New contributor
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
The issue is with the spaces in the filenames. The filenames are split on spaces. When cp
gets more than two arguments, the last argument has to be a directory. It's not, so it complains.
To remove the Edexcel International GCSE Physics
string from each filename and to convert spaces to underscores in a safe way, use (in bash
)
for name in 'Edexcel International GCSE Physics '*.docx; do
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$name" "$newname"
done
This iterates over all relevant files in the current directory and creates a new name in the variable newname
by first deleting the known substring from the very start of the name, and then converting the remaining spaces into underscores. The old name is then renamed to the new name.
Change the mv
to cp
if you actually want to create copies of the files (as in your code).
Testing:
$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
(the loop is run here)
$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx
Would you want to apply this recursively on a number of subdirectories:
find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
for pathname; do
name=$(basename "$pathname")
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$pathname" "$(dirname "$pathname")/$newname"
done' sh +
Related:
- Why does my shell script choke on whitespace or other special characters?
- Why is looping over find's output bad practice?
- Understanding the -exec option of `find`
OK, I get thatcp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works?
– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given toecho
, which is why they showed in the output. See the difference betweenprintf '%sn' 'hello world'
andprintf '%sn' 'hello world'
.
– Kusalananda♦
yesterday
@AndrewWoodward Theecho
command outputted a correct command. That does not mean that the input toecho
was a correct command.
– Kusalananda♦
yesterday
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
|
show 1 more comment
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',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Andrew Woodward is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f511891%2fcp-target-is-not-a-directory-during-while-loop%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The issue is with the spaces in the filenames. The filenames are split on spaces. When cp
gets more than two arguments, the last argument has to be a directory. It's not, so it complains.
To remove the Edexcel International GCSE Physics
string from each filename and to convert spaces to underscores in a safe way, use (in bash
)
for name in 'Edexcel International GCSE Physics '*.docx; do
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$name" "$newname"
done
This iterates over all relevant files in the current directory and creates a new name in the variable newname
by first deleting the known substring from the very start of the name, and then converting the remaining spaces into underscores. The old name is then renamed to the new name.
Change the mv
to cp
if you actually want to create copies of the files (as in your code).
Testing:
$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
(the loop is run here)
$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx
Would you want to apply this recursively on a number of subdirectories:
find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
for pathname; do
name=$(basename "$pathname")
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$pathname" "$(dirname "$pathname")/$newname"
done' sh +
Related:
- Why does my shell script choke on whitespace or other special characters?
- Why is looping over find's output bad practice?
- Understanding the -exec option of `find`
OK, I get thatcp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works?
– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given toecho
, which is why they showed in the output. See the difference betweenprintf '%sn' 'hello world'
andprintf '%sn' 'hello world'
.
– Kusalananda♦
yesterday
@AndrewWoodward Theecho
command outputted a correct command. That does not mean that the input toecho
was a correct command.
– Kusalananda♦
yesterday
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
|
show 1 more comment
The issue is with the spaces in the filenames. The filenames are split on spaces. When cp
gets more than two arguments, the last argument has to be a directory. It's not, so it complains.
To remove the Edexcel International GCSE Physics
string from each filename and to convert spaces to underscores in a safe way, use (in bash
)
for name in 'Edexcel International GCSE Physics '*.docx; do
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$name" "$newname"
done
This iterates over all relevant files in the current directory and creates a new name in the variable newname
by first deleting the known substring from the very start of the name, and then converting the remaining spaces into underscores. The old name is then renamed to the new name.
Change the mv
to cp
if you actually want to create copies of the files (as in your code).
Testing:
$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
(the loop is run here)
$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx
Would you want to apply this recursively on a number of subdirectories:
find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
for pathname; do
name=$(basename "$pathname")
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$pathname" "$(dirname "$pathname")/$newname"
done' sh +
Related:
- Why does my shell script choke on whitespace or other special characters?
- Why is looping over find's output bad practice?
- Understanding the -exec option of `find`
OK, I get thatcp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works?
– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given toecho
, which is why they showed in the output. See the difference betweenprintf '%sn' 'hello world'
andprintf '%sn' 'hello world'
.
– Kusalananda♦
yesterday
@AndrewWoodward Theecho
command outputted a correct command. That does not mean that the input toecho
was a correct command.
– Kusalananda♦
yesterday
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
|
show 1 more comment
The issue is with the spaces in the filenames. The filenames are split on spaces. When cp
gets more than two arguments, the last argument has to be a directory. It's not, so it complains.
To remove the Edexcel International GCSE Physics
string from each filename and to convert spaces to underscores in a safe way, use (in bash
)
for name in 'Edexcel International GCSE Physics '*.docx; do
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$name" "$newname"
done
This iterates over all relevant files in the current directory and creates a new name in the variable newname
by first deleting the known substring from the very start of the name, and then converting the remaining spaces into underscores. The old name is then renamed to the new name.
Change the mv
to cp
if you actually want to create copies of the files (as in your code).
Testing:
$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
(the loop is run here)
$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx
Would you want to apply this recursively on a number of subdirectories:
find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
for pathname; do
name=$(basename "$pathname")
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$pathname" "$(dirname "$pathname")/$newname"
done' sh +
Related:
- Why does my shell script choke on whitespace or other special characters?
- Why is looping over find's output bad practice?
- Understanding the -exec option of `find`
The issue is with the spaces in the filenames. The filenames are split on spaces. When cp
gets more than two arguments, the last argument has to be a directory. It's not, so it complains.
To remove the Edexcel International GCSE Physics
string from each filename and to convert spaces to underscores in a safe way, use (in bash
)
for name in 'Edexcel International GCSE Physics '*.docx; do
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$name" "$newname"
done
This iterates over all relevant files in the current directory and creates a new name in the variable newname
by first deleting the known substring from the very start of the name, and then converting the remaining spaces into underscores. The old name is then renamed to the new name.
Change the mv
to cp
if you actually want to create copies of the files (as in your code).
Testing:
$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
(the loop is run here)
$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx
Would you want to apply this recursively on a number of subdirectories:
find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
for pathname; do
name=$(basename "$pathname")
newname=$name#Edexcel International GCSE Physics
newname=$newname// /_
mv -i "$pathname" "$(dirname "$pathname")/$newname"
done' sh +
Related:
- Why does my shell script choke on whitespace or other special characters?
- Why is looping over find's output bad practice?
- Understanding the -exec option of `find`
edited yesterday
answered yesterday
Kusalananda♦Kusalananda
141k17263439
141k17263439
OK, I get thatcp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works?
– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given toecho
, which is why they showed in the output. See the difference betweenprintf '%sn' 'hello world'
andprintf '%sn' 'hello world'
.
– Kusalananda♦
yesterday
@AndrewWoodward Theecho
command outputted a correct command. That does not mean that the input toecho
was a correct command.
– Kusalananda♦
yesterday
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
|
show 1 more comment
OK, I get thatcp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) whycp
in thewhile
loop seems to be ignoring the quotes, because theecho
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of thatecho
output into the command line works?
– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given toecho
, which is why they showed in the output. See the difference betweenprintf '%sn' 'hello world'
andprintf '%sn' 'hello world'
.
– Kusalananda♦
yesterday
@AndrewWoodward Theecho
command outputted a correct command. That does not mean that the input toecho
was a correct command.
– Kusalananda♦
yesterday
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
OK, I get that
cp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) why cp
in the while
loop seems to be ignoring the quotes, because the echo
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of that echo
output into the command line works?– Andrew Woodward
yesterday
OK, I get that
cp
will choke on filenames containing spaces, which is why I put the quotes in. What I'm still puzzled about is (1) why cp
in the while
loop seems to be ignoring the quotes, because the echo
clearly shows only two names - the source with spaces (quoted) and the target without spaces, and (2) why a direct copy/paste of that echo
output into the command line works?– Andrew Woodward
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given to
echo
, which is why they showed in the output. See the difference between printf '%sn' 'hello world'
and printf '%sn' 'hello world'
.– Kusalananda♦
yesterday
@AndrewWoodward You inserted literal single quotes. These are interpreted as part of the actual value given to
echo
, which is why they showed in the output. See the difference between printf '%sn' 'hello world'
and printf '%sn' 'hello world'
.– Kusalananda♦
yesterday
@AndrewWoodward The
echo
command outputted a correct command. That does not mean that the input to echo
was a correct command.– Kusalananda♦
yesterday
@AndrewWoodward The
echo
command outputted a correct command. That does not mean that the input to echo
was a correct command.– Kusalananda♦
yesterday
1
1
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Yeah, after a bit of testing it finally clicked! Duh... Thanks :)
– Andrew Woodward
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
Double quoting parameter expansions would have saved all of this trouble, as it would have prevented the word-splitting.
– D. Ben Knoble
yesterday
|
show 1 more comment
Andrew Woodward is a new contributor. Be nice, and check out our Code of Conduct.
Andrew Woodward is a new contributor. Be nice, and check out our Code of Conduct.
Andrew Woodward is a new contributor. Be nice, and check out our Code of Conduct.
Andrew Woodward is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f511891%2fcp-target-is-not-a-directory-during-while-loop%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
-bash, cp, quoting