Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hi,
I'd like to join about 100 "*.eps" files which are located in different subdirectories of a directory . please show me the best way and tell me how.(please guide me step by step---I'm a newbie ! )
Much much thanks in advance.
If it's possible teach me an easy way to produce a caption for each one.
<edit>
Note that "path/to/files" is the name of the directory (or "folder" to use the desktop metaphor) containing the directories containing the .eps files. For example, if you didn't mind waiting for the search to finish, and all the eps files were under your home directory, the command to list them all would be find ~/ -name *.eps.
And, since you mentioned that you weren't (yet) too familiar with the Linux bash "command line" language, the expression $(<some command>) means "the result that would have been displayed if the command was run outside of the $( . . . )capture function. (And, to confuse even more, instead of $( . . . ) you can use ` . . . `, but do be careful: those are back-quotes, not single-quotes in the alternative expression.)
And cat is a command that concatenates all the files in it's argument list into a single file that's written to the "standard output" (i.e., your display). Except that the > redirects the "standard output" to the file named after the >.
</edit>
Last edited by PTrenholme; 11-11-2009 at 03:14 PM.
Well, yes, I can see where you'd have a problem. The secret is to use the whole command inside the $(), not just the arguments to the command. The whole command is, again, cat $(find /path/to/files -name "*.eps") > /path/to/combined_eps_file or, using your example, cat $(find ~/ -name "*.eps") > out.eps where I highlighted the part you left out in red.
Suggestion: Select the whole command, press Ctrl-C to copy it, go to you terminal window, and press Ctrl-Shift-V to paste the command into the terminal. (Please don't forget the "Shift" in the paste part. For historical reasons, a "terminal window" is emulating an old display system, and those system used unshifted control characters for special purposes.)
<edit>
Another thing to remember, if you're use to other computer systems, is that Linux systems are casesensitive, and almost all commands must be entered in lower case.
</edit>
Last edited by PTrenholme; 11-12-2009 at 08:58 AM.
Again Thanks ; I did as you said and found just one of '.eps ' files in created 'out.eps', receiving as below in terminal:: (I should say that I had 5 '.eps' files in the folder[Noushin@81 ~]$ )
[Noushin@81 ~]$ cat $(find ~/ -name "*.eps") > out.eps
cat: /home/Noushin/2BAND-GSimpson/U-scan/0.4/n220eta0.1/u=0.4: No such file or directory
cat: eta=0.01-n=220.eps: No such file or directory
cat: /home/Noushin/2BAND-GSimpson/U-scan/0.4/n220eta0.01/u=0.4: No such file or directory
cat: eta=0.01-n=220.eps: No such file or directory
cat: /home/Noushin/.Trash/out: No such file or directory
cat: (4th: No such file or directory
cat: copy).eps: No such file or directory
cat: /home/Noushin/.Trash/out: No such file or directory
cat: (3rd: No such file or directory
cat: copy).eps: No such file or directory
cat: /home/Noushin/.Trash/out: No such file or directory
cat: (copy).eps: No such file or directory
cat: /home/Noushin/.Trash/out: No such file or directory
cat: (another: No such file or directory
cat: copy).eps: No such file or directory
[Noushin@81 ~]$
Besides this problem , May you tell me how to join the files that are in different directories and in a large number??
Ah, well, things get trickier when the file names contain blanks since bash, by default, uses white-space as its field delimiter. So, try this: IFS=$'\n';cat "$(find ~/ -name '*.eps')" > out.eps
where the input field delimiter is reset to the new-line character by the IFS=$'\n' and the double-quotes around the $(...) tell bash to return each field surrounded by quotes.
As for your second question, generally speaking cat will concatenate every file in its argument list into the file specified to the right of the redirection symbol (the >). If you'd feel more comfortable processing fewer files, or if you get an error message that you've exceeded the maximum number of characters permitted in a command line, then something like this might work: IFS=$'\n';files="cat "$(find ~/ -name '*.eps')";echo-n ""> out.eps;for f in "${files}";do echo "${f}" >> out.eps;cat "${f}" >> out.eps;done
Now, that's actually a "bash script" which could be written like this:
PHP Code:
#!/bin/bash # Change the field separator to be only a newline character IFS=$'\n' # Get the list of all *.eps files inside or under the user's home directory files="$(find ~/ -name '*.eps')" # Create an empty output file echo -n "">out.eps # Loop through the list of files returned by the find command for f in "${files}" do # Add the input file name to the output as a "caption" (You can, of course, echo anything you want here.) echo "${f}" >> out.eps # And copy the file contents to the out.eps file cat "${f}" >> out.eps done
Note that a single redirection symbol (>) means "create or replace the output file with the redirected output" and a doubled redirection symbol (>>) means "append the redirected output to the existing file contents."
Well, the output file you created was out.eps, and the file that cat could not find was 1/n800/ImReGa33.eps.
Try cat out.eps instead. (The argument of the redirection directive (the > or >>) is the name of the file to which the output is redirected.)
I've written a script that you might be able to use, but it is completely untested. The UNTESTED script is below. To use it, copy it to a file and use the command chmod o+x to make it executable. Then run it by entering the file name (folled by the arguments) in a terminal window. Use file_name --help for a description of the arguments an their defaults.
I'm sorry that I haven't been able to test the script, but I have just been released from the hospital following major surgery, and find my energy level quite low.
Here's the script:
Code:
#!/bin/bash
# Script to create a set of directories containing N subdirectories from all the subdirectories of a given directory
#
function local_help()
{
cat <<EOF
$0: Create a set of directories containing N subdirectories from all the subdirectories of a given directory
Usage $0 [-h | --help] {[-N | --size] nunber} {[-B | --base] string} {[-D | --source] path} {[-G | --grouped] path}
Options: -h | --help : Print this message
-N number : Number of sub-irectories in each group [Default: 20]
-D path : Path to directory containig the sub-directories to be grouped [Default: Current directory]
-G path : Path to directory to contain the grouped sub-directories [Default: ../Groups]
-B string : Base name for groups if sub-directories [Default: COMPLETE]
EOF
exit 0
}
function abort()
{
echo $0: Error $@ >&2
exit 1
}
# Do we have any arguments? If not, print the help message and abort.
[ $# -eq 0 ] && local_help
#
# Parse the arguments
Opt=$(getopt -o hN::n::D::d::G::g::B::b:: --long help size base source grouped -n "$0" -- "$@")
# Did that work?
[ $? -ne 0 ] && echo $0: Could not parse arguments. Aborting. >>&2 && exit 1
eval set -- "$Opt"
#
# Set the default argument values
N=20 # Number of sub-directories in each group
D="$(pwd)" # Directory containg the sub-directories to be grouped
G="$D"/../groups # Directory to contain the groups of N sub-directories
B="COMPLETE" # Base name for groups
while true ; do
case "$1" in
-h|--help) local_help;;
-N|-n|--size)
case "$2" in
"") shift 2 ;;
*) N=$2 ; shift 2 ;;
esac ;;
-D|-d|--source)
case "$2" in
"") shift 2 ;;
*) D=$2 ; shift 2 ;;
esac ;;
-G|-g|--grouped)
case "$2" in
"") shift 2 ;;
*) G=$2 ; shift 2 ;;
esac ;;
-B|-b|--base)
case "$2" in
"") shift 2 ;;
*) B=$2 ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo $0: Error parsing arguments ; exit 1 ;;
esac
done
# Sanity checks
[ -d "$D" ] || abort "\"$D\" is not a directory"
[ -d "$G" ] || ( mkdir "$G" && [ $? -ne 0 ] && abort "\"$G\" does not exist and could not be created.")
#
# Find the last used group number
L=0
dirs=$(find "$G" -name "$B"* -prune -print0)
if ! [ -z "$dirs" ]
then
IFS=$'\x0'
for d in $dirs
do
M=$(($($d/*$B/)))
[ $M -gt $L ] && L=$M
done
fi
#
# Get the list of sub-directories of $D
dirs=$(find "$D" -type d -prune -print0)
[ -z "$dirs" ] && abort "\"$D\" contained no subdirectories."
#
# Set the initial values
count=0
M=$(($M+1))
out="$G"/"$B"_$M
mkdir -p "$out"
[ $? -ne 0 ] && abort "Could not create output directory \"$out\"."
#
# Move the sub-directories in groups of N into the group directory
for d in $dirs
do
count=$(($count+1))
if [ $count -gt $N ]
then
M=$(($M+1))
out="$G"/"$B"_$M
mkdir -p "$out"
[ $? -ne 0 ] && abort "Could not create output directory \"$out\"."
count=1
fi
mv "$d" "$out"
[ $? -ne 0 ] && abort "Could not move \"$d\" into directory \"$out\"."
done
<edit>
By the way, I notice from your output that you're logged in as "root," instead of logging in as a regular used. Be warned that the above script, if run as "root," may cause irreparable harm you your system and will, at least, create subdirectories in unexpected places.
Several of the access-control checks on which the script relies will be bypassed if it is run with "root" access.
Note also that, as a general rule, "root" access should only be used foe administrative pruposes, and never used when running scripts provided by strangers over the Internet.
</edit>
Last edited by PTrenholme; 11-15-2009 at 12:35 PM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.