Below files are present in current directory.
-rw-r--r-- 1 kazama kazama 0 Feb 16 08:50 london_july_2001_001.jpeg
-rw-r--r-- 1 kazama kazama 0 Feb 16 08:50 london_march_2004_002.png
-rw-r--r-- 1 kazama kazama 0 Feb 16 08:50 newyork_dec_2012_005.jpeg
-rw-r--r-- 1 kazama kazama 0 Feb 16 08:50 paris_sept_2007_003.jpg
I want to filter all images except which starts with "paris" text.
I have tried below command which works as per my expectation.
ls -l !(paris*)
But, I do not understand why below 2 commands do not give me expected output. In both of the cases it shows all the 4 files.
ls -l !(paris)*.*(jpeg|jpg|png)
ls -l !(paris)*
How bash interprets this extended globbing syntax internally ?Is it first trying to match !(paris) then it tries to match (jpeg|jpg|png) ?
!(paris) matches anything but paris, which includes paris_, pari, par, pa, p, and even the empty string. Bash will find something that doesn't match paris and try to match the rest of the pathname against the rest of the pattern. See:
$ echo !(paris)london*
london_july_2001_001.jpeg london_march_2004_002.png
$ echo !(paris)_*
london_july_2001_001.jpeg london_march_2004_002.png newyork_dec_2012_005.jpeg paris_sept_2007_003.jpg
$ echo !(paris)_*_*_*
london_july_2001_001.jpeg london_march_2004_002.png newyork_dec_2012_005.jpeg
Related
I have some 1080x1920 png files and I want to crop them into 1080x1728 with offset-y 65, so I tried and it returns this:
gimp -i -b '(gimp-image-crop "*.png" 1080 1728 0 65)' -b '(gimp-quit 0)'
$ ll
total 1796
drwxrwxr-x 2 cat cat 4096 Jul 25 15:06 ./
drwxrwxr-x 4 cat cat 4096 Jul 25 14:37 ../
-rwxrwxr-x 1 cat cat 278356 Jul 9 10:56 1.png*
-rwxrwxr-x 1 cat cat 278356 Jul 9 10:56 Screenshot_20210709-105437.png*
-rwxrwxr-x 1 cat cat 58088 Jul 9 10:56 Screenshot_20210709-105445.png*
-rwxrwxr-x 1 cat cat 108385 Jul 9 14:54 Screenshot_20210709-145331.png*
-rwxrwxr-x 1 cat cat 130486 Jul 9 22:18 Screenshot_20210709-221631.png*
-rwxrwxr-x 1 cat cat 133602 Jul 9 22:20 Screenshot_20210709-221834.png*
-rwxrwxr-x 1 cat cat 153976 Jul 9 22:22 Screenshot_20210709-222035.png*
-rwxrwxr-x 1 cat cat 149365 Jul 9 22:23 Screenshot_20210709-222039.png*
-rwxrwxr-x 1 cat cat 124369 Jul 11 17:01 Screenshot_20210711-165959.png*
-rwxrwxr-x 1 cat cat 138719 Jul 24 23:06 Screenshot_20210724-230338.png*
-rwxrwxr-x 1 cat cat 88272 Jul 24 23:06 Screenshot_20210724-230346.png*
-rwxrwxr-x 1 cat cat 104779 Jul 24 23:06 Screenshot_20210724-230356.png*
-rwxrwxr-x 1 cat cat 63867 Jul 24 23:05 Screenshot_20210724-230408.png*
$ gimp -i -b '(gimp-image-crop "*.png" 1080 1728 0 65)' -b '(gimp-quit 0)'
batch command experienced an execution error:
Error: Invalid type for argument 1 to gimp-image-crop
$
It always returns Invalid type for argument 1 to gimp-image-crop.
I check in Procedure Browser in GIMP and it tells:
The argument 1 is "THE IMAGE". I also tried "1.png" and ".+png" but it always returns the same error: Error: Invalid type for argument 1 to gimp-image-crop
I don't understand which part I do wrong.
My OS is Linux Mint 20.2 Cinnamon and GIMP version is 2.10.18.
Please help.
The image argument of gimp-image-crop is the handle of a loaded image in Gimp, not an image file. So you have to gimp-file-load the image (this gives you a handle), apply your operations, and then gimp-file-save. Note that saving an image to a "flat" format (JPG, PNG...) is actually saving a layer, so if your image is more than one layer you may have to first create a layer to save using gimp-layer-new-from-visible.
This said, agreed that in most cases it is faster to use ImageMagick.
I have a bunch of MP4 files that look like this:
-rw-rw-r-- 1 116M Apr 19 06:08 lULIqx9Akn4.mp4
These are youtube videos. When I try to do anything with all of them, I get a weird error. Every command I try says that I'm using invalid options (that I am not using). Here are some examples.
$ ls *.mp4
/bin/ls: invalid option -- '7'
Try '/bin/ls --help' for more information.
$ mv *.mp4 videos/
mv: invalid option -- 'L'
Try 'mv --help' for more information.
$ cp *.mp4 videos/.
cp: invalid option -- '7'
Try 'cp --help' for more information.
It doesn't do the same thing with a different extension (*.mp3, *.txt, *.sh).
What's going on? How do I fix this?
I used this as a cheap workaround,
find . -name "*.mp4" -exec mv {} videos/. \;
but I want to understand what's happening, not just get the job done.
One of your filenames starts with a hyphen, e.g,. -7 or -L. Try ls -- *.mp4 or cp -- *.mp4 videos. Also, allow me to suggest UNIX and Linux Stack Exchange for shell questions :) .
Solution:
Either move the files,
mv -- *.mp4 ./videos
or rename the files in situ...
for file in -*.mp4; do mv -- "$file" "${file:1}"; done
Explanation:
My sense is you have a file with a leading - in the directly... most commands stop you creating such files but if you copy them from another operating system it can occur. Thus, you need to rename any files with a leading - in their filename...
Let me explain with an example...
Let's try to create a file with a leading -:
touch "-7ULIqx9Akn4.mp4"
touch: illegal option -- 7
we can get around this as follows:
>touch -- "-7ULIqx9Akn4.mp4"
> ls -al -- -*.mp4
total 0
-rw-r--r--# 1 n staff 0 Apr 29 13:02 -7ULIqx9Akn4.mp4
ok, now lets set up an example and demonstrate a solution...
> ls -la
total 0
-rw-r--r--# 1 n staff 0 Apr 29 12:49 -75438752.mp4
-rw-r--r--# 1 n staff 0 Apr 29 12:49 -85438750.mp4
drwxr-xr-x# 7 n staff 238 Apr 29 12:49 .
drwxr-xr-x# 6 n staff 204 Apr 29 11:18 ..
-rw-r--r--# 1 n staff 0 Apr 29 12:36 75438750.mp4
-rw-r--r--# 1 n staff 0 Apr 29 12:33 7ULIqx9Akn4.mp4
-rw-rw-r--# 1 n staff 0 Apr 29 11:19 lULIqx9Akn4.mp4
next:
ls -- -*.mp4
-75438752.mp4 -85438750.mp4
ok, lets now rename these files...
A little explanation here, the following command uses mv to remove the leading character. i.e. Find files with a leading - and remove the leading character {$file:1} from the filename...
for file in -*.mp4; do mv -- "$file" "${file:1}"; done
Result:
> for file in -*.mp4; do mv -- "$file" "${file:1}"; done
> ll
total 0
drwxr-xr-x# 7 n 238 Apr 29 12:52 ./
drwxr-xr-x# 6 n 204 Apr 29 11:18 ../
-rw-r--r--# 1 n 0 Apr 29 12:36 75438750.mp4
-rw-r--r--# 1 n 0 Apr 29 12:49 75438752.mp4
-rw-r--r--# 1 n 0 Apr 29 12:33 7ULIqx9Akn4.mp4
-rw-r--r--# 1 n 0 Apr 29 12:49 85438750.mp4
-rw-rw-r--# 1 n 0 Apr 29 11:19 lULIqx9Akn4.mp4
Note
The above does not account for duplicate file names...
Here is my scenario:
well i use csh
1)
$ ls -l /corefiles/ | grep "root"
-rw-r----- 1 root root 0 Sep 22 2014 core.3.4.
-rwxr-x--- 1 root root 92 Sep 22 2014 ss.sh
2)
$ set textInfo=`ls -l /corefiles/ | grep "root"`
$ echo $textInfo
-rw-r----- 1 root root 0 Sep 22 2014 core.3.4. -rwxr-x--- 1 root root 92 Sep 22 2014 ss.sh
But I need echo $textInfo to give output like 1).
How can I achieve this? I do not want to redirect the content into a file.
I need to store console output in a variable but with the same format as present in the console.
I need a variable which has content as below:
$ echo $textInfo
-rw-r----- 1 root root 0 Sep 22 2014 core.3.4.
-rwxr-x--- 1 root root 92 Sep 22 2014 ss.sh
Use echo "$textInfo" instead of echo $textInfo. Otherwise the variable is expanded as part of the command line instead of as a string, so the newlines aren't preserved.
try this:
textInfo=$(ls -l /corefiles/ | grep "root")
then
echo "$textInfo"
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 years ago.
Improve this question
I have two files in my home folder named "'?" and "'?;?" (without the double quotes). How can I delete them? I've tried to use escape, but it doesn't work.
Use single or double quotes to avoid wildcard expansion. A ? is a wildcard which indicates to the shell to match with any one single character. By placing it in quotes you are telling the shell not to perform wildcard expansion.
rm '?' '?;?'
rm "?" "?;?"
This will remove the two files named "?" and "?;?"
You can also use a backslash to quote the individual characters that have special meaning to the shell, so you could do this
rm \? \?\;\?
Notice you have to quote the '?' to prevent pathname expansion and you have to quote the ';' so the shell doesn't interpret that as separating commands.
If you leave out the quotes, then the shell parses it differently. Here's an experiment I ran.
$ for i in {1..4}; do for j in {a..c}; do touch "$i;$j" $j '?' '?;?';done;done
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ? ?;? a b c
$ rm ? ?;?
rm: cannot remove `?': No such file or directory
rm: cannot remove `a': No such file or directory
rm: cannot remove `b': No such file or directory
rm: cannot remove `c': No such file or directory
bash: ?: command not found
$ rm `echo "?" "?;?"`
rm: cannot remove `?': No such file or directory
$
What happened here is the shell did pathname expansion, so
rm ? ?;?
became
rm ? a b c ? a b c;? a b c
The rm command removed files a b c ? then complained that the following files were not found (they had already been deleted). The semicolon separated commands, so it then tried to invoke the '?' command passing arguments "a" "b" "c" ... but there is no '?' command - the file named '?' had just been deleted, and it wasn't executable anyway - so the shell complains that the "?" command is not found.
If you want to remove all files matching "?" and "?;?" you need to trick the shell into expanding those, which I did like this
rm `echo "?" "?;?"`
This was expanded by the shell in two steps, first it runs echo "?" "?;?" which results in two strings, "?" and "?;?", then it does pathname expansion using those strings to produce the arguments for rm, which results in
rm ? 1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ?;?
Notice that the wildcard expansion for '?' didn't produce any matching files this time (they had already been previously deleted), so the shell passes '?' as an argument to rm, which successfully removes all files passed as arguments except for '?' so it complains about that.
Here's another experiment
$ for i in {1..4}; do for j in {a..c}; do touch "$i;$j" $j '?' '?;?';done;done
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c ? ?;? a b c
$ rm "?" "?;?"
$ ls
1;a 1;b 1;c 2;a 2;b 2;c 3;a 3;b 3;c 4;a 4;b 4;c a b c
$ rm `echo "?" "?;?"`
$ ls
$
For more information consult the man page on globbing
man 7 glob
Wildcard Matching
A string is a wildcard pattern if it contains one of the characters '?', '*' or '['. Globbing is the operation that
expands a wildcard pattern into the list of pathnames matching the pattern. Matching is defined by:
A '?' (not between brackets) matches any single character.
A '*' (not between brackets) matches any string, including the empty string.
Note that ls can report a question mark for arbitrary non-printable characters, so there's a chance that what you've got as a file name does not contain a question mark.
You can spot this with the ls -b command, or with ls | cat.
As a convoluted example, complete with remedy, I created a script convolvulus like this:
set -x
mkdir convoluted &&
(
cd convoluted
cp /dev/null "$(ls -la | sed 1d)"
ls
ls -b
ls | cat
ls -la | cat
cp /dev/null $'\n'
cp /dev/null $'\n;\n'
ls -als | cat
ls -lab
ls
ls | cat
rm $'\n' $'\n;\n' d*
ls -a
)
rm -fr convoluted
When run, it yielded:
$ bash convolvulus 2>&1 | so
+ mkdir convoluted
+ cd convoluted
++ ls -la
++ sed 1d
+ cp /dev/null 'drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..'
+ ls
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -b
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .\ndrwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
+ cat
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -la
+ cat
total 0
drwxr-xr-x 3 jleffler staff 102 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ cp /dev/null '
'
+ cp /dev/null '
;
'
+ ls -als
+ cat
total 0
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58
;
0 drwxr-xr-x 5 jleffler staff 170 Mar 9 11:58 .
0 drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
0 -rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls -lab
total 0
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 \n
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 \n;\n
drwxr-xr-x 5 jleffler staff 170 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
-rw-r--r-- 1 jleffler staff 0 Mar 9 11:58 drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .\ndrwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
;
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ ls
+ cat
;
drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..
+ rm '
' '
;
' 'drwxr-xr-x 2 jleffler staff 68 Mar 9 11:58 .
drwxr-xr-x 240 jleffler staff 8160 Mar 9 11:58 ..'
+ ls -a
.
..
+ rm -fr convoluted
$
Have fun!
The -b option to ls works for GNU ls and for Mac OS X and BSD ls (but is not defined by POSIX).
The '$'\n' notation is Bash ANSI-C Quoting.
Use quotes around the file names:
$ ls
? ?;?
$ rm '?'
$ ls
?;?
$ rm "?;?"
$ ls
$
Using the tcsh shell on Free BSD, is there a way to recursively list all files and directories including the owner, group and relative path to the file?
ls -alR comes close, but it does not show the relative path in front of every file, it shows the path at the top of a grouping i.e.
owner% ls -alR
total 0
drwxr-xr-x 3 owner group 102 Feb 1 10:50 .
drwx------+ 27 owner group 918 Feb 1 10:49 ..
drwxr-xr-x 5 owner group 170 Feb 1 10:50 subfolder
./subfolder:
total 16
drwxr-xr-x 5 owner group 170 Feb 1 10:50 .
drwxr-xr-x 3 owner group 102 Feb 1 10:50 ..
-rw-r--r-- 1 owner group 0 Feb 1 10:50 file1
-rw-r--r-- 1 owner group 0 Feb 1 10:50 file2
What I would like is output like:
owner group ./relative/path/to/file
The accepted answer to this question shows the relative path to a file, but does not show the owner and group.
How about this:
find . -exec ls -dl \{\} \; | awk '{print $3, $4, $9}'
Use tree. Few linux distributions install it by default (in these dark days of only GUIs :-), but it's always available in the standard repositories. It should be available for *BSD also, see http://mama.indstate.edu/users/ice/tree/
Use:
tree -p -u -g -f -i
or
tree -p -u -g -f
or check the man page for many other useful arguments.
Works in Linux Debian:
find $PWD -type f
find comes close:
find . -printf "%u %g %p\n"
There is also "%P", which removes the prefix from the filename, if you want the paths to be relative to the specified directory.
Note that this is GNU find, I don't know if the BSD find also supports -printf.
You've already got an answer that works, but for reference you should be able to do this on the BSDs (I've tested it on a mac) :
find . -ls
If you fancy using Perl don't use it as a wrapper around shell commands. Doing it in native Perl is faster, more portable, and more resilient. Plus it avoids ad-hoc regexes.
use File::Find;
use File::stat;
find (\&myList, ".");
sub myList {
my $st = lstat($_) or die "No $file: $!";
print getgrnam($st->gid), " ",
getpwuid($st->uid), " ",
$File::Find::name, "\n";
}
Simple way I found was this:
ls -lthr /path_to_directory/*
" * " - represents levels.
Ajiths-MBP:test ajith$ ls -lthr *
test2:
total 0
-rw-r--r-- 1 ajith staff 0B Oct 17 18:22 test2.txt
test3:
total 0
-rw-r--r-- 1 ajith staff 0B Oct 17 18:22 test3.txt
test1:
total 0
-rw-r--r-- 1 ajith staff 0B Oct 17 18:21 test1.txt
drwxr-xr-x 3 ajith staff 96B Oct 17 18:22 test1_sub_dir
Ajiths-MBP:test ajith$ ls -lthr */*
-rw-r--r-- 1 ajith staff 0B Oct 17 18:21 test1/test1.txt
-rw-r--r-- 1 ajith staff 0B Oct 17 18:22 test2/test2.txt
-rw-r--r-- 1 ajith staff 0B Oct 17 18:22 test3/test3.txt
test1/test1_sub_dir:
total 0
-rw-r--r-- 1 ajith staff 0B Oct 17 18:22 test1_sub_file.txt
Use a shell script. Or a Perl script. Example Perl script (because it's easier for me to do):
#!/usr/bin/perl
use strict;
use warnings;
foreach(`find . -name \*`) {
chomp;
my $ls = `ls -l $_`;
# an incomprehensible string of characters because it's Perl
my($owner, $group) = /\S+\s+\S+\s+(\S+)\s+(\S)+/;
printf("%-10s %-10s %s\n", $owner, $group, $_);
}
Perhaps a bit more verbose than the other answers, but should do the trick, and should save you having to remember what to type. (Code untested.)